home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / libs / phigs / ptk.lha / ptk / source / library / topo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-01  |  69.9 KB  |  2,541 lines

  1. /*----------------------------------------------------------------------------
  2.  
  3.  Module name: TopDraw
  4.  
  5.  Author: Toby Howard
  6.  
  7.  Function: Implements the PHIGS structure network topology drawing tool.
  8.  
  9.  External function list: ptk_topology.
  10.  
  11.  Internal function list:
  12.  
  13.  Hashtables used: "structureid", "name", "label".
  14.  
  15.  Modification history: (Version), (Date), (Name), (Description).
  16.  
  17.  1.0, ????, Toby Howard, First version.
  18.  
  19.  1.1, 29th July 1988, Steve Larkin, Modified to use Vax Phigs instead of 
  20.  KRT3.
  21.  
  22.  2.0, 10th June 1991, Gareth Williams, Translated to C.
  23.  
  24.  3.0, June 1992, Gareth Williams, Converted to ISO PHIGS C.
  25.  
  26. ----------------------------------------------------------------------------*/
  27.  
  28. #include <stdio.h>
  29. #include <math.h>
  30. #include <phigs.h>
  31. #include "ptk.h"
  32.  
  33. /*--------------------------------------------------------------------------*/
  34.  
  35. /* The width and height of the nodes in the diagram */
  36.  
  37. #define WIDTH              1.0
  38.  
  39. #define HEIGHT             1.0
  40.  
  41. /* The horizontal and vertical separations of the nodes */
  42.  
  43. #define HSPACING        (3.0 * WIDTH)
  44.  
  45. #define VSPACING        (4.0 * HEIGHT)
  46.  
  47. /* for storage of structure information */
  48.  
  49. typedef struct ptksstruct 
  50. {
  51.   Pint name;          /* structure identifier */
  52.   Pint numchildren;   /* number of children */
  53.   Pint numunique;     /* number of unique children */
  54.   Pint level;         /* max level in picture */
  55.   Ppoint pos;        /* position in picture */
  56.   ptkboolean placed;     /* placed yet? */
  57.   struct ptksref *firstchild, *lastchild;    /* list of children */
  58.   struct ptksref *firstparent, *lastparent;  /* list of parents */
  59.   struct ptksstruct *next;                   /* next ptksstruct record */
  60. } ptksstruct;
  61.  
  62. /*  for storage of structure references  */
  63.  
  64. typedef struct ptksref 
  65. {
  66.   ptksstruct *structptr;  /* structure being referenced */
  67.   Pint element;          /* element doing the referencing */
  68.   struct ptksref *next;      /* next ptksreference */
  69. } ptksref;
  70.  
  71. /* this is a node in the diagram */
  72.  
  73. typedef struct ptksnode 
  74. {
  75.   ptksstruct *structptr;
  76.   struct ptksnode *next;
  77. } ptksnode;
  78.  
  79. /* this is for the list of rows */
  80.  
  81. typedef struct ptksrow 
  82. {
  83.   Pint num;
  84.   ptksnode *n;
  85.   struct ptksrow *next;
  86. } ptksrow;
  87.  
  88. typedef struct ptkskeytable 
  89. {
  90.   char key[256], an[256];
  91. } ptkskeytable;
  92.  
  93. typedef struct ptkstopdraw 
  94. {
  95.   Pint topologyid;
  96.   Pint topologystid;
  97.   ptketopologytype topologytype;
  98.   Pint txfont;
  99.   Pint textcolour;
  100.   Pint linecolour;
  101.   Pint edgecolour;
  102.   Pint intcolour;
  103.   Pint topologyname;
  104.   Pint_list posted;
  105.   
  106.   /* highlight node */
  107.   Pint highlightnode;
  108.   Pint highlightedge;
  109.   Pint highlightint;
  110.  
  111.   struct ptkstopdraw *next;
  112.   
  113.   Pint root;
  114.  
  115.   Pint_list hlist;               /* list of nodes to highlight ? */
  116.   ptksstruct *structlist;      /* the head of the structure info list */
  117.   ptksrow *rowlist;            /* the head of the row list */
  118.  
  119.   Pmatrix3 globaltran, mat;
  120.   Pelem_ref_list_list *pathlist;     /* structure network paths */
  121.   Pstore pathdata;               /* buffer to hold paths data */
  122.  
  123.   Pfloat annotextheight;     /* size of characters for annotation */
  124.   Pint nodebounds;           /* for drawing the nodes */
  125.   Ppoint nodepoints[5];
  126.   Pfloat nodeheight, nodewidth;
  127.  
  128.   Plimit3 extent;
  129.   Pfloat xinc, yinc;
  130.   Pfloat rowmaxx[255];
  131.   Pfloat topx, topy;
  132.   Pint maxlevel;
  133.   
  134.   ptkskeytable keytablelst[255];
  135.   Pint keyno;
  136. } ptkstopdraw;
  137.  
  138. /*--------------------------------------------------------------------------*/
  139.  
  140. static ptkstopdraw *topptr = NULL;
  141.  
  142. static ptkstopdraw *firsttop = NULL;
  143. static ptkstopdraw *lasttop = NULL;
  144. static nodeidcount = 0;
  145.  
  146. static topologycount = 0;
  147.  
  148. /*--------------------------------------------------------------------------*/
  149.  
  150. static void settop(C(Pint) topid)
  151. PreANSI(Pint topid)
  152. {
  153.   ptkstopdraw *ptr;
  154.  
  155.   if (firsttop == NULL)
  156.   {
  157.     topptr = NULL;
  158.     return;
  159.   }
  160.   ptr = firsttop;
  161.   while (ptr->topologyid != topid)
  162.   {
  163.     ptr = ptr->next;
  164.     if (ptr == NULL)
  165.     {
  166.       topptr = NULL;
  167.       return;
  168.     }
  169.   }
  170.   topptr = ptr;
  171. }  /* settop */
  172.  
  173. /*--------------------------------------------------------------------------*/
  174.  
  175. static void note(C(Pfloat) xx, C(Pfloat) yy)
  176. PreANSI(Pfloat xx)
  177. PreANSI(Pfloat yy)
  178. /*
  179. ** \parambegin
  180. ** \param{}{xx}{x coordinate}{IN}
  181. ** \param{}{yy}{y coordinate}{IN}
  182. ** \paramend
  183. ** \blurb{Updates `extent' using xx, yy.}
  184. */
  185. {
  186.   if (xx > topptr->extent.x_max)
  187.     topptr->extent.x_max = xx;
  188.   if (yy > topptr->extent.y_max)
  189.     topptr->extent.y_max = yy;
  190.   if (xx < topptr->extent.x_min)
  191.     topptr->extent.x_min = xx;
  192.   if (yy < topptr->extent.y_min)
  193.     topptr->extent.y_min = yy;
  194. }  /* note */
  195.  
  196. /*--------------------------------------------------------------------------*/
  197.  
  198. /* Key handling
  199. **
  200. ** When the algorithm has drawn the nodes for all the structures in
  201. ** the hierarchy, it attempts to draw the structure names against the nodes,
  202. ** and tries various positions to avoid overlapping with adjacent nodes. If
  203. ** it is unable to place the text reasonably, it gives up, and resorts to
  204. ** a simple 'key' scheme, where the name is associated with a key, and the
  205. ** node is labelled with the key instead of the full name (the assumption
  206. ** being that the key will be only a few characters long. If keys are used, a
  207. ** list of keys and their corresponding names is added to the picture at the
  208. ** end.
  209. */
  210.  
  211. /*--------------------------------------------------------------------------*/
  212.  
  213. static void setkey(C(char *) v, C(char *) k)
  214. PreANSI(char *v)
  215. PreANSI(char *k)
  216. /*
  217. ** \parambegin
  218. ** \param{}{v}{string to allocate a key for}{IN}
  219. ** \param{}{k}{key allocated to string ( a, b etc.)}{IN}
  220. ** \paramend
  221. ** \blurb{Allocates a key to string 'v', and records the correspondence
  222. ** in the key table.}
  223. */
  224. {
  225.   ptkskeytable *keyptr;
  226.  
  227.   topptr->keyno++;
  228.   keyptr = &topptr->keytablelst[topptr->keyno - 1];
  229.   keyptr->key[1] = '\0';
  230.   keyptr->key[0] = (char)(topptr->keyno + 96);
  231.  
  232.   /* keys are labelled from 'a' upwards */
  233.   strcpy(k, keyptr->key);   /* return the key allocated */
  234.   strcpy(keyptr->an, v);
  235. }  /* setkey */
  236.  
  237. /*--------------------------------------------------------------------------*/
  238.  
  239. static void drawkeys(C(void))
  240. /*
  241. ** \blurb{Start the list of keys at xmin, and drop a node's
  242. ** worth below the minimum y.}
  243. */
  244. {
  245.   Pint i;
  246.   Ppoint tp;
  247.   ptkskeytable *keyptr;
  248.   char str[256];
  249.  
  250.   if (topptr->keyno > 0)
  251.   {
  252.     tp = ptk_point(topptr->extent.x_min,
  253.                   topptr->extent.y_min - topptr->nodeheight);
  254.     for (i = 0; i < topptr->keyno; i++) 
  255.     {
  256.       keyptr = &topptr->keytablelst[i];
  257.       sprintf(str, "%s    %s", keyptr->key, keyptr->an);
  258.       tp.y -= topptr->annotextheight * 1.5;
  259.       ptext(&tp, str);
  260.     }
  261.     /* Record the limits of the keytable */
  262.     note(tp.x, tp.y); 
  263.   }
  264. }  /* drawkeys */
  265.  
  266. /*--------------------------------------------------------------------------*/
  267.  
  268. static void setscaling(C(void))
  269. /*
  270. ** \blurb{Computes the transformation to scale the picture
  271. ** into [0,1], and inserts a setglobaltran at the start of the picture.}
  272. */
  273. {
  274.   Ppoint3 sc, sh;
  275.   Pint err, el;
  276.   Pfloat height, width, scale;
  277.   Ppoint3 topshift, topscale;
  278.  
  279.   topptr->extent.x_min -= topptr->nodewidth;
  280.   topptr->extent.x_max += topptr->nodewidth;
  281.   topptr->extent.y_min -= topptr->nodeheight;
  282.   topptr->extent.y_max += topptr->nodeheight;
  283.   height = topptr->extent.y_max - topptr->extent.y_min;
  284.   width = topptr->extent.x_max - topptr->extent.x_min;
  285.   scale = 1.0/PTKMAX(height, width);
  286.   topshift = ptk_point3(-topptr->extent.x_min - (width / 2.0),
  287.                         -topptr->extent.y_min - (height / 2.0), 0.0), 
  288.   ptk_shift3(&topshift, PTYPE_REPLACE, topptr->globaltran); 
  289.   topscale = ptk_point3(scale, scale, scale);
  290.   ptk_scale3(&topscale, PTYPE_POSTCONCAT, topptr->globaltran);
  291.   topshift = ptk_point3(0.5, 0.5, 0.0);
  292.   ptk_shift3(&topshift, PTYPE_POSTCONCAT, topptr->globaltran); 
  293.   /* Squeeze in a global transformation at the
  294.      top of the structure */
  295.   pset_elem_ptr(0);
  296.   pset_elem_ptr_label(ptk_stringtoint("label", "globaltran"));
  297.   pset_global_tran3(topptr->globaltran);
  298. }  /* setscaling */
  299.  
  300. /*--------------------------------------------------------------------------*/
  301.  
  302. static ptkboolean overlap(C(Ppoint *) p, C(Pfloat) stringw, C(Pfloat) stringh)
  303. PreANSI(Ppoint *p)
  304. PreANSI(Pfloat stringw)
  305. PreANSI(Pfloat stringh)
  306. /*
  307. ** \parambegin
  308. ** \param{}{p}{point to check for overlapping nodes}{IN}
  309. ** \param{}{stringw}{character string width}{IN}
  310. ** \param{}{stringh}{character string height}{IN}
  311. ** \paramend
  312. ** \blurb{Given a point p, checks against all the positioned nodes 
  313. ** to see if any lie between p and and another point q, 'stringw' 
  314. ** horizontally away from p.
  315. ** Returns TRUE if there is an overlapping node, otherwise FALSE.}
  316. */
  317. {
  318.   ptksstruct *sp;
  319.   ptkboolean over;
  320.  
  321.   over = FALSE;
  322.   sp = topptr->structlist;
  323.   while (sp != NULL && !over) 
  324.   {   
  325.     /* look at each node */
  326.     if ((p->y <= sp->pos.y + topptr->nodeheight / 2.0) &&
  327.     (p->y + stringh >= sp->pos.y - topptr->nodeheight / 2.0)) 
  328.     {
  329.       /* it overlaps the node vertically, so now test if the
  330.          node lies somewhere inside the extent */
  331.       if ((p->x < sp->pos.x + topptr->nodewidth / 2.0) &&
  332.       (p->x + stringw > sp->pos.x - topptr->nodewidth / 2.0))
  333.     over = TRUE;
  334.     }
  335.     sp = sp->next;
  336.   }
  337.   return over;
  338. }  /* overlap */
  339.  
  340. /*--------------------------------------------------------------------------*/
  341.  
  342. static void setnode(C(Pfloat) w, C(Pfloat) h)
  343. PreANSI(Pfloat w)
  344. PreANSI(Pfloat h)
  345. /*
  346. ** \parambegin
  347. ** \param{}{w}{node width}{IN}
  348. ** \param{}{h}{node height}{IN}
  349. ** \paramend
  350. ** \blurb{Establishes the size of a node, centred.}
  351. */
  352. {
  353.   topptr->nodebounds = 5;
  354.   topptr->nodepoints[0] = ptk_point(w/-2.0, h/-2.0);
  355.   topptr->nodepoints[1] = ptk_point(w/2.0, h/-2.0);
  356.   topptr->nodepoints[2] = ptk_point(w/2.0, h/2.0);
  357.   topptr->nodepoints[3] = ptk_point(w/-2.0, h/2.0);
  358.   topptr->nodepoints[4] = ptk_point(w/-2.0, h/-2.0);
  359.   pset_char_ht(h/2.0);
  360.   topptr->annotextheight = h / 2.0;
  361. }  /* setnode */
  362.  
  363. /*--------------------------------------------------------------------------*/
  364.  
  365. static void initialise(C(void))
  366. /*
  367. ** \blurb{Initialise topdraw values.}
  368. */
  369. {
  370.   Pint k;
  371.  
  372.   topptr->structlist = NULL;   /* no structures to start with */
  373.   topptr->rowlist = NULL;   /* and no rows */
  374.   topptr->keyno = 0;   /* no debugging printing, no keys */
  375.   for (k = 0; k <= 254; k++)
  376.     topptr->rowmaxx[k] = -32768.0;
  377.   topptr->maxlevel = 1;
  378. }  /* initialise */
  379.  
  380. /*--------------------------------------------------------------------------*/
  381.  
  382. static ptkboolean lookupstructure(C(Pint) sn, C(ptkboolean) create, 
  383.                                C(ptksstruct **) sp)
  384. PreANSI(Pint sn)
  385. PreANSI(ptkboolean create)
  386. PreANSI(ptksstruct **sp)
  387. /*
  388. ** \parambegin
  389. ** \param{}{sn}{structure identifier to look up}{IN}
  390. ** \param{}{create}{add to structlist if TRUE, do nothing if FALSE}{IN}
  391. ** \param{}{sp}{pointer to structure record}{IN}
  392. ** \paramend
  393. ** \blurb{Looks for a structure in the namelist, and inserts it
  394. ** if it's not there, and create=TRUE. Returns a pointer to the name
  395. ** record, or NIL if it wasn't found and not created. The result is 
  396. ** TRUE if it was created.
  397. ** Returns TRUE if new record created, otherwise FALSE.}
  398. */
  399. {
  400.   ptkboolean found;
  401.   ptksstruct *last, *s, *news;
  402.  
  403.   s = topptr->structlist;
  404.   found = FALSE;
  405.   *sp = NULL;
  406.   while (!found && s != NULL) 
  407.   {
  408.     found = (sn == s->name);
  409.     if (found)
  410.       break;
  411.     last = s;
  412.     s = s->next;
  413.   }
  414.   if (found) 
  415.   {
  416.     *sp = s;
  417.     return (!found && create);
  418.   }
  419.   if (!create) 
  420.   {
  421.     return (!found && create);
  422.   }  /* not found and created */
  423.   news = (ptksstruct *)malloc(sizeof(ptksstruct));
  424.   *sp = news;
  425.   if (topptr->structlist == NULL)   /* initialise the record */
  426.     topptr->structlist = news;
  427.   else
  428.     last->next = news;
  429.   news->name = sn;
  430.   news->level = 0;
  431.   news->next = NULL;
  432.   news->numchildren = ptk_countchildren(sn);
  433.   news->numunique = ptk_countuniqchildren(sn);
  434.   news->firstchild = NULL;
  435.   news->lastchild = NULL;
  436.   news->firstparent = NULL;
  437.   news->lastparent = NULL;
  438.   news->placed = FALSE;
  439.   news->pos = ptk_point(0.0, 0.0);
  440.   return (!found && create);
  441. }  /* lookupstructure */
  442.  
  443. /*--------------------------------------------------------------------------*/
  444.  
  445. static void drawnames(C(void))
  446. /*
  447. ** \blurb{Draws the name of the structure next to its node.
  448. ** First we'll try and draw the string to the right of the node, which
  449. ** seems like a good place. If that would splash over another node
  450. ** nearby,we'll try the left instead. If both are no good, give up,and
  451. ** use a key instead.}
  452. */
  453. {
  454.   Ppoint tp;
  455.   ptksstruct *sp;
  456.   Pmatrix3 mat;
  457.   Pint textrep;
  458.   char k[256], annot[256];
  459.   Ptext_align a;
  460.   Pint lenstr;
  461.   ptkboolean donames;
  462.  
  463.   ptk_unitmatrix3(mat);
  464.   pset_local_tran3(mat, PTYPE_REPLACE);
  465.   a.hor = PHOR_NORM;
  466.   a.vert = PVERT_HALF;
  467.   pset_text_align(&a);
  468.   donames = ptk_hashtableused("structureid");
  469.   sp = topptr->structlist;   /* going to scan the structure list */
  470.   while (sp != NULL) 
  471.   {
  472.     /* place text to the right of the node */
  473.     tp = ptk_point(sp->pos.x + 3.0 * WIDTH / 4.0, sp->pos.y);
  474.     if (donames)
  475.     {
  476.       ptk_inttostring("structureid", sp->name, 256, annot, &lenstr);
  477.       if (lenstr == 0)
  478.         sprintf(annot, "%d\0", sp->name); 
  479.     }
  480.     else
  481.       sprintf(annot, "%d\0", sp->name); 
  482.     /* should use inqtextextent to get width of string */
  483.     if (overlap(&tp, (Pfloat)strlen(annot) * topptr->annotextheight,
  484.         topptr->annotextheight)) 
  485.     {
  486.       /* no good. now try to place it to the left of the node */
  487.       tp.x = sp->pos.x - topptr->nodewidth / 2.0 -
  488.          (Pfloat)strlen(annot) * topptr->annotextheight;
  489.       if (overlap(&tp, strlen(annot) * topptr->annotextheight,
  490.           topptr->annotextheight)) 
  491.       {
  492.     /* Need to resort to a key here. Reset the text position
  493.        to inside the node, and get a key */
  494.         tp = ptk_point(sp->pos.x + 3.0 * WIDTH / 4.0, sp->pos.y);
  495.     setkey(annot, k);
  496.         note(tp.x + topptr->annotextheight, tp.y);
  497.     ptext(&tp, k);
  498.       } 
  499.       else 
  500.       {  
  501.         /* place text to the left */
  502.     note(tp.x, tp.y);
  503.     tp.x = sp->pos.x - topptr->nodeheight * 3.0 / 4.0;
  504.     a.hor = PHOR_RIGHT;
  505.     a.vert = PVERT_HALF;
  506.     pset_text_align(&a);
  507.     ptext(&tp, annot);
  508.     a.hor = PHOR_NORM;
  509.     a.vert = PVERT_HALF;
  510.     pset_text_align(&a);
  511.       }
  512.     } 
  513.     else 
  514.     {  
  515.       /* no overlap */
  516.       note(tp.x + (Pfloat)strlen(annot) * topptr->annotextheight, tp.y);
  517.       ptext(&tp, annot);
  518.     }
  519.     sp = sp->next;
  520.   }
  521. }  /* drawnames */
  522.  
  523. /*--------------------------------------------------------------------------*/
  524.  
  525. static Pint findlowestchild(C(ptksstruct *) root)
  526. PreANSI(ptksstruct *root)
  527. /*
  528. ** \parambegin
  529. ** \param{}{root}{pointer to root structure record}{IN}
  530. ** \paramend
  531. ** \blurb{Looks at all the immediate children of 'root', and
  532. ** returns the level of the deepest one.
  533. ** Returns level of lowest child of root.}
  534. */
  535. {
  536.   ptksref *r;
  537.   Pint l;
  538.  
  539.   l = 0;
  540.   r = root->firstchild;
  541.   while (r != NULL) 
  542.   {
  543.     if (r->structptr->level > l)
  544.       l = r->structptr->level;
  545.     r = r->next;
  546.   }
  547.   return l;
  548. }  /* findlowestchild */
  549.  
  550. /*--------------------------------------------------------------------------*/
  551.  
  552. static void placetree(C(ptksstruct *) root, C(Pfloat *) x, C(Pfloat) y)
  553. PreANSI(ptksstruct *root)
  554. PreANSI(Pfloat *x)
  555. PreANSI(Pfloat y)
  556. /*
  557. ** \parambegin
  558. ** \param{}{root}{pointer to root structure record.}{IN}
  559. ** \param{}{x}{x coordinate of node}{IN}
  560. ** \param{}{y}{y coordinate of node}{IN}
  561. ** \paramend
  562. ** \blurb{Places a subtree.}
  563. */
  564. {
  565.   Pint n, fudge;
  566.   ptksref *r;
  567.   Pfloat fuzz, finetune, xx, xxinc;
  568.  
  569.   if (root->placed)
  570.     return;
  571.  
  572.   n = root->numunique;
  573.  
  574.   fudge = findlowestchild(root) - root->level;
  575.  
  576.   finetune = 1.0;
  577.   xxinc = topptr->xinc * fudge * finetune;
  578.  
  579.   xx = *x - ((Pfloat)n - 1.0) * xxinc / 2.0;
  580.   fuzz = topptr->nodewidth * 1.5;
  581.  
  582.   if (n > 1) 
  583.   {   
  584.     /* at least one child */
  585.     if (xx <= topptr->rowmaxx[root->level] + fuzz) 
  586.     {
  587. /*      printf("adjusting for overlap at level %ld\n", root->level + 1); */
  588.       /* compute x pos of leftmost child */
  589.       xx = topptr->rowmaxx[root->level] + xxinc;
  590.       /* now readjust x to center node over its children */
  591.       *x = xx + ((Pfloat)n - 1.0) * xxinc / 2.0;
  592.     }
  593.   }
  594.  
  595.   y = 0.0 - root->level * topptr->yinc;
  596.  
  597.   root->pos = ptk_point(*x, y);
  598.  
  599.   topptr->rowmaxx[root->level - 1] = *x;
  600.  
  601.   root->placed = TRUE;
  602.  
  603.   r = root->firstchild;
  604.   while (r != NULL) 
  605.   {
  606.     placetree(r->structptr, &xx, y);
  607.     r = r->next;
  608.     xx += xxinc;
  609.   }
  610. }  /* placetree */
  611.  
  612. /*--------------------------------------------------------------------------*/
  613.  
  614. static void placenodes(C(void))
  615. /*
  616. ** \blurb{Draws all the nodes for the structures in the hierarchy.}
  617. */
  618. {
  619.   topptr->topx = 0.0;
  620.   topptr->topy = 0.0;
  621.   topptr->nodeheight = 1.0;
  622.   topptr->nodewidth = 1.0;
  623.   setnode(1.0, 1.0);
  624.   topptr->xinc = topptr->nodewidth * 2.0;
  625.   topptr->yinc = topptr->nodeheight * 2.0;
  626.       
  627.   /* start it off with a silly value */
  628.  
  629.   topptr->extent = ptk_limit3(1000000.0, -10000000.0, 10000000.0,
  630.                                -10000000.0, 0.0, 1.0);
  631.  
  632.   /* Recursively place all the nodes, starting at 0,0. The diagram
  633.   ** will grow downwards, and its ultimate extent will be in `extent'.
  634.   ** Everytime a new bit is drawn, its position is noted with `note',
  635.   ** which updates the extent. 
  636.   */
  637.  
  638.   placetree(topptr->structlist, &topptr->topx, topptr->topy);
  639. }  /* placenodes */
  640.  
  641. /*--------------------------------------------------------------------------*/
  642.  
  643. static void drawnode(C(ptksstruct *) sp)
  644. PreANSI(ptksstruct *sp)
  645. /*
  646. ** \parambegin
  647. ** \param{}{sp}{pointer to structure record}{IN}
  648. ** \paramend
  649. ** \blurb{Draws a node to represent the structure at sp in the
  650. ** structure list, and the node will go into the diagram at xx, yy.}
  651. */
  652. {
  653.   Ppoint3 sh;
  654.   Ppoint_list sets;
  655.   Pint err, elptr;
  656.  
  657.   sh = ptk_point3(sp->pos.x, sp->pos.y, 0.0);
  658.   ptk_shift3(&sh, PTYPE_REPLACE, topptr->mat);
  659.   sets.num_points = topptr->nodebounds;
  660.   sets.points = topptr->nodepoints;
  661.   if (nodeidcount == topptr->highlightnode)
  662.   {
  663.     /* jump to `highlightnode' label */
  664.     pinq_elem_ptr(&err, &elptr);
  665.     pset_elem_ptr(0);
  666.     pset_elem_ptr_label(ptk_stringtoint("label", "highlightnode"));
  667.     pset_pick_id(sp->name);
  668.     pset_local_tran3(topptr->mat, PTYPE_REPLACE);
  669.     ptk_fillareaset(1, &sets);
  670.     /* jump back */
  671.     pset_elem_ptr(elptr + 3);
  672.   }
  673.   else
  674.   {
  675.     pset_pick_id(sp->name);
  676.     pset_local_tran3(topptr->mat, PTYPE_REPLACE);
  677.     ptk_fillareaset(1, &sets);
  678.   }
  679.   note(sp->pos.x, sp->pos.y);
  680. }  /* drawnode */
  681.  
  682. /*--------------------------------------------------------------------------*/
  683.  
  684. static void drawnodes(C(void))
  685. /*
  686. ** \blurb{Draw all nodes in structure network.}
  687. */
  688. {
  689.   ptksstruct *s;
  690.  
  691.   s = topptr->structlist;
  692.   nodeidcount = 0;
  693.   while (s != NULL) 
  694.   {
  695.     drawnode(s);
  696.     nodeidcount++;
  697.     s = s->next;
  698.   }
  699. }  /* drawnodes */
  700.  
  701. /*--------------------------------------------------------------------------*/
  702.  
  703. static void drawstructnetnode(C(ptksstruct *) sp)
  704. PreANSI(ptksstruct *sp)
  705. /*
  706. ** \parambegin
  707. ** \param{}{sp}{pointer to structure record}{IN}
  708. ** \paramend
  709. ** \blurb{Draws a node to represent the structure at sp in the
  710. ** structure list, and the node will go into the diagram at xx, yy.}
  711. */
  712. {
  713.   Plimit3 boundbox, nodebox;
  714.   Pmatrix3 matrix;
  715.   Pint err, elptr;
  716.   Ppoint3 sh;
  717.  
  718.   if (ptk_boundingbox(sp->name, &boundbox, TRUE))
  719.   {
  720.     nodebox = ptk_limit3(-0.5, 0.5, -0.5, 0.5, 0.0, 1.0); 
  721.     sh = ptk_point3(sp->pos.x, sp->pos.y, 0.0);
  722.     ptk_shift3(&sh, PTYPE_REPLACE, topptr->mat);
  723.     ptk_box3tobox3(&boundbox, &nodebox, TRUE, PTYPE_PRECONCAT, topptr->mat, 
  724.                    &err);
  725.     /* jump to `globaltran' label, this avoids attribute inheritance
  726.     ** from the topology structure.
  727.     */
  728.     pinq_elem_ptr(&err, &elptr);
  729.     pset_elem_ptr(0);
  730.     pset_elem_ptr_label(ptk_stringtoint("label", "globaltran"));
  731.     pset_pick_id(sp->name);
  732.     pset_local_tran3(topptr->mat, PTYPE_REPLACE);
  733.     pexec_struct(sp->name);
  734.     /* jump back */
  735.     pset_elem_ptr(elptr + 3);
  736.     note(sp->pos.x, sp->pos.y);
  737.   }
  738.   else
  739.     drawnode(sp);
  740. }  /* drawstructnetnode */
  741.  
  742. /*--------------------------------------------------------------------------*/
  743.  
  744. static delstructnodes()
  745. {
  746.   char sname[80];
  747.   ptksstruct *s;
  748.  
  749.   s = topptr->structlist;
  750.   while (s != NULL)
  751.   {
  752.     if (s->numchildren > 0)
  753.     {
  754.       sprintf(sname, "ptk$topologynode%d", s->name);
  755.       pdel_struct(ptk_stringtoint("structureid", sname));
  756.       ptk_delstring("structureid", sname);
  757.     }
  758.     s = s->next;
  759.   }
  760. } /* delstructnodes */
  761.  
  762. /*--------------------------------------------------------------------------*/
  763.  
  764. static void drawstructnode(C(ptksstruct *) sp)
  765. PreANSI(ptksstruct *sp)
  766. /*
  767. ** \parambegin
  768. ** \param{}{sp}{pointer to structure record}{IN}
  769. ** \paramend
  770. ** \blurb{Draws a node to represent the structure at sp in the
  771. ** structure list, and the node will go into the diagram at xx, yy.}
  772. */
  773. {
  774.   Plimit3 boundbox, nodebox;
  775.   Pmatrix3 matrix;
  776.   Pint err, numchild, elptr, stendptr[2], lstnum;
  777.   Ppoint3 sh;
  778.   char sname[255];
  779.   Pelem_type elemlist[1];
  780.   Psearch_status srchstat;
  781.   ptkboolean validbox;
  782.  
  783.   validbox = ptk_boundingbox(sp->name, &boundbox, FALSE);
  784.   if (validbox)
  785.   {
  786.     if (sp->numchildren > 0)
  787.     {
  788.       sprintf(sname, "ptk$topologynode%d", sp->name);
  789.       if (!ptk_structexists(ptk_stringtoint("structureid", sname)))
  790.       {
  791.         ptk_openstruct(ptk_stringtoint("structureid", sname));
  792.         pcopy_all_elems_struct(sp->name);
  793.         /* remove all execute structs */
  794.         elptr = 0;
  795.         elemlist[0] = PELEM_EXEC_STRUCT;
  796.         pset_elem_ptr(0);
  797.         do
  798.         {
  799.           ptk_findelemtype(elemlist, 1, PDIR_FORWARD, &srchstat, &elptr, &lstnum);
  800.           if (srchstat == PSEARCH_STATUS_SUCCESS)
  801.           {
  802.             pset_elem_ptr(elptr);
  803.             pdel_elem();
  804.           }
  805.         } while (srchstat == PSEARCH_STATUS_SUCCESS);
  806.         ptk_closestruct();
  807.       }
  808.       if (validbox)
  809.       {
  810.         sh = ptk_point3(sp->pos.x, sp->pos.y, 0.0);
  811.         ptk_shift3(&sh, PTYPE_REPLACE, topptr->mat);
  812.         nodebox = ptk_limit3(-0.5, 0.5, -0.5, 0.5, 0.0, 1.0); 
  813.         ptk_box3tobox3(&boundbox, &nodebox, TRUE, PTYPE_PRECONCAT, 
  814.                        topptr->mat, &err);
  815.         pinq_elem_ptr(&err, &elptr);
  816.         pset_elem_ptr(0);
  817.         pset_elem_ptr_label(ptk_stringtoint("label", "globaltran"));
  818.         pset_pick_id(sp->name);
  819.         pset_local_tran3(topptr->mat, PTYPE_REPLACE);
  820.         pexec_struct(ptk_stringtoint("structureid", sname));
  821.         pset_elem_ptr(elptr + 3);
  822.         note(sp->pos.x, sp->pos.y);
  823.       }
  824.     }
  825.     else
  826.     {
  827.       sh = ptk_point3(sp->pos.x, sp->pos.y, 0.0);
  828.       ptk_shift3(&sh, PTYPE_REPLACE, topptr->mat);
  829.       nodebox = ptk_limit3(-0.5, 0.5, -0.5, 0.5, 0.0, 1.0);
  830.       ptk_box3tobox3(&boundbox, &nodebox, TRUE, PTYPE_PRECONCAT, topptr->mat, 
  831.                      &err);
  832.       pinq_elem_ptr(&err, &elptr);
  833.       pset_elem_ptr(0);
  834.       pset_elem_ptr_label(ptk_stringtoint("label", "globaltran"));
  835.       pset_pick_id(sp->name);
  836.       pset_local_tran3(topptr->mat, PTYPE_REPLACE);
  837.       pexec_struct(sp->name);
  838.       pset_elem_ptr(elptr + 3);
  839.       note(sp->pos.x, sp->pos.y);
  840.     }
  841.   }
  842.   else
  843.     drawnode(sp);
  844. }  /* drawstructnode */
  845.  
  846. /*--------------------------------------------------------------------------*/
  847.  
  848. static void drawstructnetnodes(C(void))
  849. /*
  850. ** \blurb{Draw all nodes in structure network.}
  851. */
  852. {
  853.   ptksstruct *s;
  854.  
  855.   s = topptr->structlist;
  856.   while (s != NULL) 
  857.   {
  858.     drawstructnetnode(s);
  859.     s = s->next;
  860.   }
  861. }  /* drawstructnetnodes */
  862.  
  863. /*--------------------------------------------------------------------------*/
  864.  
  865. static void drawstructnodes(C(void))
  866. /*
  867. ** \blurb{Draw all nodes in structure network.}
  868. */
  869. {
  870.   ptksstruct *s;
  871.  
  872.   s = topptr->structlist;
  873.   while (s != NULL) 
  874.   {
  875.     drawstructnode(s);
  876.     s = s->next;
  877.   }
  878. }  /* drawstructnodes */
  879.  
  880. /*--------------------------------------------------------------------------*/
  881.  
  882. static void drawarc(C(Pint) n, C(ptksstruct *) pp, C(ptksstruct *) pc)
  883. PreANSI(Pint n)
  884. PreANSI(ptksstruct *pp)
  885. PreANSI(ptksstruct *pc)
  886. /*
  887. ** \parambegin
  888. ** \param{}{n}{number of reference to p}{IN}
  889. ** \param{}{pp}{pointer to parent record}{IN}
  890. ** \param{}{pc}{pointer to child record}{IN}
  891. ** \paramend
  892. ** \blurb{Draws the connecting arc to show a reference to 'child'
  893. ** by 'parent'. It is 'parent's nth reference.}
  894. */
  895. {
  896.   Ppoint p[2];
  897.   Ppoint_list pts;
  898.  
  899.   p[0] = ptk_point(pp->pos.x - topptr->nodewidth / 2 +
  900.      n * topptr->nodewidth / (pp->numchildren + 1),
  901.          pp->pos.y - topptr->nodeheight / 2);
  902.   p[1] = ptk_point(pc->pos.x, pc->pos.y + topptr->nodeheight / 2);
  903.   pts.num_points = 2;
  904.   pts.points = p;
  905.   ppolyline(&pts);
  906. }  /* drawarc */
  907.  
  908. /*--------------------------------------------------------------------------*/
  909.  
  910. static void drawconnections(C(void))
  911. /*
  912. ** \blurb{This is called when all the structures' nodes have been 
  913. ** placed, and draws the arcs between the nodes which represent structure
  914. ** references.}
  915. */
  916. {
  917.   ptksstruct *s;
  918.   ptksref *child;
  919.   Pint childno;
  920.  
  921.   /* Wipe out the effects of any local trans for the nodes */
  922.   ptk_unitmatrix3(topptr->mat);
  923.   pset_local_tran3(topptr->mat, PTYPE_REPLACE);
  924.   s = topptr->structlist;
  925.   while (s != NULL) 
  926.   {   
  927.     /* process each structure in turn */
  928.     child = s->firstchild;
  929.     childno = 0;
  930.     while (child != NULL) 
  931.     {   
  932.       /* process each child in order */
  933.       childno++;
  934.       drawarc(childno, s, child->structptr);
  935.       child = child->next;
  936.     }
  937.     s = s->next;
  938.   }
  939. }  /* drawconnections */
  940.  
  941. /*--------------------------------------------------------------------------*/
  942.  
  943. static void addreference(C(ptksstruct *) pp, C(ptksstruct *) cp, C(Pint) e)
  944. PreANSI(ptksstruct *pp)
  945. PreANSI(ptksstruct *cp)
  946. PreANSI(Pint e)
  947. /*
  948. ** \parambegin
  949. ** \param{}{pp}{pointer to parent record}{IN}
  950. ** \param{}{cp}{pointer to child record}{IN}
  951. ** \param{}{e}{element pointer}{IN}
  952. ** \paramend
  953. ** \blurb{Stores a reference to 'child' at element e in 'parent'.}
  954. */
  955. {
  956.   ptksref *newref;
  957.  
  958.   newref = (ptksref *)malloc(sizeof(ptksref));
  959.   /* create a new reference node */
  960.   if (pp->firstchild == NULL)
  961.     pp->firstchild = newref;
  962.   else
  963.     pp->lastchild->next = newref;
  964.   pp->lastchild = newref;
  965.   newref->structptr = cp;
  966.   newref->element = e;
  967.   newref->next = NULL;
  968. }  /* addreference */
  969.  
  970. /*--------------------------------------------------------------------------*/
  971.  
  972. static void storereferences(C(void))
  973. /*
  974. ** \blurb{Runs along the structlist, inquiring the children of
  975. ** each structure, and storing the reference information.}
  976. */
  977. {
  978.   ptksstruct *s, *cp;
  979.   Pint e, err, foundel, tempstruct, errnum, numelts;
  980.   Psearch_status status;
  981.   ptkselcontent elcont;
  982.   Pint lstnum;
  983.   Pstore store;
  984.   Pelem_type exectype;
  985.   Pelem_type_list includelst, excludelst;
  986.  
  987.   s = topptr->structlist;
  988.   includelst.num_elem_types = 1;
  989.   exectype = PELEM_EXEC_STRUCT;
  990.   includelst.elem_types = &exectype;
  991.   excludelst.num_elem_types = 0;
  992.   excludelst.elem_types = NULL;
  993.   while (s != NULL) 
  994.   {
  995.     e = 0;
  996.     numelts = ptk_elemcount(s->name);
  997.     do
  998.     {
  999.       pelem_search(s->name, e, PDIR_FORWARD, &includelst, &excludelst, &err, 
  1000.                 &status, &foundel);
  1001.       e = foundel + 1;
  1002.       if (status == PSEARCH_STATUS_SUCCESS) 
  1003.       {
  1004.         pcreate_store(&err, &store);
  1005.     ptk_inqelemtypesizecontent(s->name, foundel, store, &errnum,
  1006.                                    &elcont);
  1007.         tempstruct = elcont.eldata->int_data;
  1008.         ptk_delstore(store);
  1009.         lookupstructure(tempstruct, FALSE, &cp);
  1010.         addreference(s, cp, foundel);
  1011.       }
  1012.     } while ((status != PSEARCH_STATUS_FAILURE) && (e <= numelts));
  1013.     s = s->next;   /* next structure */
  1014.   }
  1015. }  /* storereferences */
  1016.  
  1017. /*--------------------------------------------------------------------------*/
  1018.  
  1019. static ptksrow *selectrow(C(Pint) l, C(ptksrow **) last)
  1020. PreANSI(Pint l)
  1021. PreANSI(ptksrow **last)
  1022. /*
  1023. ** \blurb{Tries to return the address of the start of the `l'th row.
  1024. ** If this row doesn't exist yet, rowptr is NIL, and a pointer
  1025. ** to the previous row, if any, is returned in 'last'.}
  1026. */
  1027. {
  1028.   ptksrow *r;
  1029.   Pint lev;
  1030.  
  1031.   r = topptr->rowlist;
  1032.   lev = 1;
  1033.   *last = NULL;
  1034.   while (r != NULL && lev != l) 
  1035.   {
  1036.     *last = r;
  1037.     r = r->next;
  1038.     lev++;
  1039.   }
  1040.   return r;
  1041. }  /* selectrow */
  1042.  
  1043. /*--------------------------------------------------------------------------*/
  1044.  
  1045. static void addtorowlist(C(ptksstruct *) sp, C(Pint) level)
  1046. PreANSI(ptksstruct *sp)
  1047. PreANSI(Pint level)
  1048. /*
  1049. ** \blurb{Adds an entry for `sp' to the `level'th row; also records
  1050. ** the level in the structure entry.}
  1051. */
  1052. {
  1053.   ptksrow *last, *r, *newr;
  1054.   ptksnode *np, *newnp, *lastnp;
  1055.  
  1056.   r = selectrow(level, &last);
  1057.   if (r == NULL) 
  1058.   {   
  1059.     /* the required level doesn't yet exist */
  1060.     newr = (ptksrow *)malloc(sizeof(ptksrow));
  1061.     if (last == NULL)
  1062.       topptr->rowlist = newr;
  1063.     else
  1064.       last->next = newr;
  1065.     newr->next = NULL;
  1066.     newr->num = 0;
  1067.     newr->n = NULL;
  1068.     r = newr;
  1069.   }
  1070.  
  1071.   /* So now we are at the start of a row list, which may
  1072.      or may not be empty. Add the new node to the tail of it*/
  1073.   np = r->n;
  1074.   lastnp = NULL;
  1075.   r->num++;
  1076.   while (np != NULL) 
  1077.   {
  1078.     lastnp = np;
  1079.     np = np->next;
  1080.   }
  1081.   /* now lastnp = tail */
  1082.   newnp = (ptksnode *)malloc(sizeof(ptksnode));   /*create the new node*/
  1083.   if (lastnp == NULL)   /*chain to tail*/
  1084.     r->n = newnp;   /*chain to row header*/
  1085.   else
  1086.     lastnp->next = newnp;
  1087.   newnp->structptr = sp;
  1088.   newnp->next = NULL;
  1089.   sp->level = level;
  1090.  
  1091.   /* keep track of the maximum level */
  1092.   if (level > topptr->maxlevel)
  1093.     topptr->maxlevel = level;
  1094. }  /* addtorowlist */
  1095.  
  1096. /*--------------------------------------------------------------------------*/
  1097.  
  1098. static ptksnode *selectrownode(C(ptksrow *) r, C(ptksstruct *) sp, C(ptksnode **)last)
  1099. PreANSI(ptksrow *r)
  1100. PreANSI(ptksstruct *sp)
  1101. PreANSI(ptksnode **last)
  1102. /*
  1103. ** \blurb{Locates the given structure in the given row. It's address
  1104. ** is returned as the result. Also, if there is a node immediately
  1105. ** previous to this node, its address is returned in 'last',
  1106. ** otherwise 'last' is NIL, which means that the first node in
  1107. ** the row list was found.}
  1108. */
  1109.   ptksnode *np;
  1110.   ptkboolean found;
  1111.  
  1112.   np = r->n;
  1113.   found = FALSE;
  1114.   *last = NULL;
  1115.   while (np != NULL && !found) 
  1116.   {
  1117.     if (np->structptr == sp)
  1118.       found = TRUE;
  1119.     else 
  1120.     {
  1121.       *last = np;   /* record the previous address */
  1122.       np = np->next;
  1123.     }
  1124.   }
  1125.   return np;
  1126. }  /* selectrownode */
  1127.  
  1128. /*--------------------------------------------------------------------------*/
  1129.  
  1130. static void deletefromrowlist(C(ptksstruct *) sp)
  1131. PreANSI(ptksstruct *sp)
  1132. /*
  1133. ** \blurb{Deletes the entry for sp from its row.}
  1134. */
  1135. {
  1136.   ptksrow *r, *dummy;
  1137.   ptksnode *np, *last;
  1138.  
  1139.   r = selectrow(sp->level, &dummy);
  1140.   if (r == NULL) 
  1141.   {
  1142. /*    printf("deletefromrowlist: row %d doesn't exist\n", sp->level); */
  1143.     return;
  1144.   }
  1145.   r->num--;
  1146.   np = selectrownode(r, sp, &last);
  1147.   if (np == NULL) 
  1148.   {
  1149. /*    printf("deletefromrowlist: %d not found on row %d\n",
  1150.        sp->name, sp->level); */
  1151.     return;
  1152.   }
  1153.   if (last == NULL)
  1154.     r->n = np->next;   /* first on the list */
  1155.   else
  1156.     last->next = np->next;
  1157.   free(np);
  1158. }  /* deletefromrowlist */
  1159.  
  1160. /*--------------------------------------------------------------------------*/
  1161.  
  1162. static void getpaths()
  1163. {
  1164.   Pint totsize, err;
  1165.  
  1166.   pcreate_store(&err, &topptr->pathdata);
  1167.   pinq_paths_descs(topptr->root, PORDER_TOP_FIRST, 0, topptr->pathdata,
  1168.                    &err, &topptr->pathlist);
  1169. }
  1170.  
  1171. /*--------------------------------------------------------------------------*/
  1172.  
  1173. static void buildlists(C(void))
  1174. /*
  1175. ** \blurb{Constructs the main data structures used by the topology 
  1176. ** drawer. It creates the structure list, and the row list.}
  1177. */
  1178. {
  1179.   Pint cur_level, p, path;
  1180.   ptksstruct *sp;
  1181.   ptkboolean rowentryinvalid;
  1182.  
  1183.   /* do first node */
  1184.   lookupstructure(topptr->root, TRUE, &sp);
  1185.   addtorowlist(sp, 1);
  1186.   for (p = 0; p < topptr->pathlist->num_elem_ref_lists; p++) 
  1187.   {  
  1188.     /* do a path */
  1189.     cur_level = 1;
  1190.     for (path = 0; path < topptr->pathlist->elem_ref_lists[p].num_elem_refs;
  1191.          path++) 
  1192.     {   
  1193.       /* each member of path */
  1194.       rowentryinvalid = TRUE;   /* assume it will change the row list */
  1195.       /* Look for this structure, and create it if it isn't there */
  1196.       if (!lookupstructure(topptr->pathlist->elem_ref_lists[p].elem_refs[path].struct_id, TRUE, &sp)) 
  1197.       {
  1198.     /* it was already there */
  1199.     if (sp->level < cur_level)
  1200.       deletefromrowlist(sp);
  1201.     else
  1202.       rowentryinvalid = FALSE;
  1203.       }
  1204.       if (rowentryinvalid)
  1205.     addtorowlist(sp, cur_level);
  1206.       cur_level++;
  1207.     }  /* each member of path */
  1208.     /* go to next path  */
  1209.   }  /* a path */
  1210.   storereferences();
  1211.   ptk_delstore(topptr->pathdata);
  1212. }  /* buildlists */
  1213.  
  1214. /*--------------------------------------------------------------------------*/
  1215.  
  1216.  
  1217. static void disposenodelist(C(ptksnode *) nodeptr)
  1218. PreANSI(ptksnode *nodeptr)
  1219. {
  1220.   if (nodeptr->next == NULL)
  1221.     free(nodeptr);
  1222.   else
  1223.     disposenodelist(nodeptr->next);
  1224. }
  1225.  
  1226. /*--------------------------------------------------------------------------*/
  1227.  
  1228. static void disposereflist(C(ptksref *) refptr)
  1229. PreANSI(ptksref *refptr)
  1230. {
  1231.   if (refptr->next == NULL)
  1232.     free(refptr);
  1233.   else
  1234.     disposereflist(refptr->next);
  1235. }
  1236.  
  1237. /*--------------------------------------------------------------------------*/
  1238.  
  1239. static void disposestructlist(C(ptksstruct *) stptr)
  1240. PreANSI(ptksstruct *stptr)
  1241. {
  1242.   if (stptr->next == NULL)
  1243.   {
  1244.     if (stptr->firstchild != NULL)
  1245.       disposereflist(stptr->firstchild);
  1246.     if (stptr->firstparent != NULL)
  1247.       disposereflist(stptr->firstparent);
  1248.     free(stptr);
  1249.   }
  1250.   else
  1251.     disposestructlist(stptr->next);
  1252. }
  1253.  
  1254. /*--------------------------------------------------------------------------*/
  1255.  
  1256. static void disposerowlist(C(ptksrow *) rowptr)
  1257. PreANSI(ptksrow *rowptr)
  1258. {
  1259.   if (rowptr->next == NULL)
  1260.   {
  1261.     if (rowptr->n != NULL)
  1262.       disposenodelist(rowptr->n);
  1263.     free(rowptr);
  1264.   }
  1265.   else
  1266.     disposerowlist(rowptr->next);
  1267. }
  1268.  
  1269. /*--------------------------------------------------------------------------*/
  1270.  
  1271. static inqnamelist(C(ptksstruct *) stptr, C(Pint_list *) namelist)
  1272. PreANSI(ptksstruct *stptr)
  1273. PreANSI(Pint_list *namelist)
  1274. {
  1275.   ptksref *refptr;
  1276.  
  1277.   refptr = stptr->firstchild;
  1278.   while (refptr != NULL)
  1279.   {
  1280.     if (inintlst(refptr->structptr->name, namelist) == -1)
  1281.       namelist->ints[namelist->num_ints++] = refptr->structptr->name;
  1282.     inqnamelist(refptr->structptr, namelist);
  1283.     refptr = refptr->next;
  1284.   }
  1285. }
  1286.  
  1287. /*--------------------------------------------------------------------------*/
  1288.  
  1289. static void setnodeposition(C(Pint) topid, C(Pint) nodeid, 
  1290.                                C(Ppoint *) nodept, C(ptkenodetype) nodetype)
  1291. PreANSI(Pint topid)
  1292. PreANSI(Pint nodeid)
  1293. PreANSI(Ppoint *nodept)
  1294. PreANSI(ptkenodetype nodetype)
  1295. {
  1296.   ptksstruct *structptr;
  1297.   Pint err, i, totsize;
  1298.   Ppoint3 toppt, nodept3;
  1299.   Pmatrix3 invglobalmat;
  1300.   Ppoint3 delta;
  1301.   Pint_list stids, nameset;
  1302.   Pint ids[255], name;
  1303.  
  1304.   settop(topid);
  1305.   ptk_invertmatrix3(topptr->globaltran, invglobalmat, &err);
  1306.   nodept3 = ptk_point3(nodept->x, nodept->y, 0.0);
  1307.   toppt = ptk_transform3(invglobalmat, &nodept3);
  1308.   switch (nodetype)
  1309.   {
  1310.     case PTKESINGLE: 
  1311.       structptr = topptr->structlist;
  1312.       for (i = 0; i < nodeid; i++)
  1313.         structptr = structptr->next;
  1314.       structptr->pos = ptk_point(toppt.x, toppt.y);
  1315.       break;
  1316.    
  1317.     case PTKEGROUP:
  1318.       /* calculate dx, dy,
  1319.          follow ref list, add dx, dy to position
  1320.       */
  1321.       structptr = topptr->structlist;
  1322.       for (i = 0; i < nodeid; i++)
  1323.         structptr = structptr->next;
  1324.       delta = ptk_point3(toppt.x - structptr->pos.x,
  1325.                          toppt.y - structptr->pos.y, 0.0);
  1326.       /* inquire structure identifiers of sub tree */
  1327.       stids.ints = ids;
  1328.       stids.num_ints = 1;
  1329.       ids[0] = structptr->name;
  1330.       inqnamelist(structptr, &stids);
  1331.       for (i = 0; i < stids.num_ints; i++)
  1332.       {
  1333.         structptr = topptr->structlist;
  1334.         while (structptr->name != stids.ints[i])
  1335.           structptr = structptr->next;
  1336.         structptr->pos.x += delta.x;
  1337.         structptr->pos.y += delta.y;
  1338.       }
  1339.       break;
  1340.   }
  1341.   /* remove keys */
  1342.   topptr->keyno = 0;
  1343.   for (i = 0; i <= 254; i++)
  1344.     topptr->rowmaxx[i] = -32768.0;
  1345.   ptk_openstruct(topptr->topologystid);
  1346.   pset_elem_ptr(0);
  1347.   pdel_elems_labels(ptk_stringtoint("label", "globaltran"), 
  1348.                   ptk_stringtoint("label", "highlightattrs"));
  1349.   pdel_elems_labels(ptk_stringtoint("label", "highlightnode"), 
  1350.                   ptk_stringtoint("label", "attrs"));
  1351.   pdel_elems_labels(ptk_stringtoint("label", "starttopology"), 
  1352.                   ptk_stringtoint("label", "endtopology"));
  1353.   topptr->extent = ptk_limit3(1000000.0, -10000000.0, 10000000.0,
  1354.                                -10000000.0, 0.0, 1.0);
  1355.   pset_edit_mode(PEDIT_INSERT);  
  1356.   setnode(1.0, 1.0);
  1357.   switch (topptr->topologytype)
  1358.   {
  1359.     case PTKEBOXTOPOLOGY: 
  1360.       drawnodes();
  1361.       break;
  1362.  
  1363.     case PTKESTRUCTNETTOPOLOGY:
  1364.       drawstructnetnodes();
  1365.       break;
  1366.  
  1367.     case PTKESTRUCTTOPOLOGY:
  1368.       drawstructnodes();
  1369.       break;
  1370.   }
  1371.   nameset.ints = &name;
  1372.   nameset.num_ints = 1;
  1373.   name = topptr->topologyname;
  1374.   premove_names_set(&nameset);
  1375.   drawconnections();
  1376.   drawnames();
  1377.   drawkeys();
  1378.   setscaling();
  1379.   ptk_closestruct();
  1380. }  /* setnodeposition */
  1381.  
  1382. /*--------------------------------------------------------------------------*/
  1383.  
  1384. static void redrawtopology(C(void))
  1385. {
  1386.   Pint_list nameset;
  1387.   Pint name, k;
  1388.  
  1389.   /* remove keys */
  1390.   topptr->keyno = 0;
  1391.   for (k = 0; k <= 254; k++)
  1392.     topptr->rowmaxx[k] = -32768.0;
  1393.   pempty_struct(topptr->topologystid);
  1394.   ptk_openstruct(topptr->topologystid);
  1395.   
  1396.   ptk_seteditmode(PEDIT_INSERT);   /* We want to insert elements */
  1397.   nameset.ints = &name;
  1398.   nameset.num_ints = 1;
  1399.   name = topptr->topologyname;
  1400.   padd_names_set(&nameset);
  1401.   plabel(ptk_stringtoint("label", "globaltran"));
  1402.  
  1403.   plabel(ptk_stringtoint("label", "highlightattrs"));
  1404.   pset_edge_colr_ind(topptr->highlightedge);
  1405.   pset_int_colr_ind(topptr->highlightint);
  1406.   pset_int_style(PSTYLE_SOLID);
  1407.   pset_edge_flag(PEDGE_ON);
  1408.   plabel(ptk_stringtoint("label", "highlightnode"));
  1409.   plabel(ptk_stringtoint("label", "attrs"));
  1410.   pset_line_colr_ind(topptr->linecolour);
  1411.   pset_int_colr_ind(topptr->intcolour);
  1412.   pset_edge_colr_ind(topptr->edgecolour);
  1413.   pset_text_font(topptr->txfont);
  1414.   pset_text_colr_ind(topptr->textcolour);
  1415.   plabel(ptk_stringtoint("label", "starttopology"));
  1416.  
  1417.   placenodes();
  1418.   switch (topptr->topologytype)
  1419.   {
  1420.     case PTKEBOXTOPOLOGY: 
  1421.       drawnodes();
  1422.       break;
  1423.  
  1424.     case PTKESTRUCTNETTOPOLOGY:
  1425.       drawstructnetnodes();
  1426.       break;
  1427.  
  1428.     case PTKESTRUCTTOPOLOGY:
  1429.       drawstructnodes();
  1430.       break;
  1431.   }
  1432.   premove_names_set(&nameset);
  1433.   drawconnections();
  1434.   drawnames();
  1435.  
  1436.   /* In case any nodes were labelled with keys because there was no room
  1437.      for proper annotation, draw the keytable. */
  1438.   drawkeys();
  1439.   plabel(ptk_stringtoint("label", "endtopology"));
  1440.  
  1441.   /* now we've drawn it all, so we find the appropriate scale to put it all
  1442.      in [0,1] */
  1443.   setscaling();
  1444.  
  1445.   ptk_unseteditmode();
  1446.   ptk_closestruct();    
  1447. }  /* redrawtopology */
  1448.  
  1449. /*--------------------------------------------------------------------------*/
  1450. /*--------------------- External Topology Functions ------------------------*/
  1451. /*--------------------------------------------------------------------------*/
  1452.  
  1453. static void createtopology(C(Pint) topid, C(Pint) root, C(Pint) txfont,
  1454.                          C(Pint) linecol, C(Pint) textcol, C(Pint) edgecol,
  1455.                          C(Pint) intcol, C(Pint *) error)
  1456. PreANSI(Pint topid)
  1457. PreANSI(Pint root)
  1458. PreANSI(Pint txfont)
  1459. PreANSI(Pint linecol)
  1460. PreANSI(Pint textcol)
  1461. PreANSI(Pint edgecol)
  1462. PreANSI(Pint intcol)
  1463. PreANSI(Pint *error)
  1464. /* 
  1465. ** \parambegin
  1466. ** \param{Pint}{topid}{topology identifier}{IN}
  1467. ** \param{Pint}{root}{structure network identifier}{IN}
  1468. ** \param{Pint}{txfont}{label text font}{IN}
  1469. ** \param{Pint}{linecol}{polyline colour index}{IN}
  1470. ** \param{Pint}{textcol}{text colour index}{IN}
  1471. ** \param{Pint}{edgecol}{edge colour index}{IN}
  1472. ** \param{Pint}{intcol}{interior colour index}{IN}
  1473. ** \param{Pint *}{error}{error code}{OUT}
  1474. ** \paramend
  1475. ** \blurb{Create topology diagram of given structure network.}
  1476. */
  1477. {
  1478.   Pint curname;
  1479.   char stname[255];
  1480.   Pint_list nameset;
  1481.   Pint name;
  1482.  
  1483.   /* if there already exists a topology with this identifier, error */
  1484.   *error = 0;
  1485.   settop(topid);
  1486.   if (topptr == NULL)
  1487.   {  
  1488.     if (lasttop == NULL)
  1489.     {
  1490.       firsttop = lasttop = topptr =
  1491.         (ptkstopdraw *)malloc(sizeof(ptkstopdraw));
  1492.       topptr->next = NULL;
  1493.     }
  1494.     else
  1495.     {
  1496.       lasttop->next = topptr = (ptkstopdraw *)malloc(sizeof(ptkstopdraw));
  1497.       topptr->next = NULL;
  1498.       lasttop = lasttop->next;
  1499.     }
  1500.  
  1501.     topologycount++;  
  1502.     topptr->topologyid = topid;
  1503.     topptr->posted.num_ints = 0;
  1504.     topptr->posted.ints = (Pint *)calloc(10, sizeof(Pint));
  1505.     sprintf(stname, "ptk$topology%d", topid);
  1506.     topptr->topologystid = ptk_stringtoint("structureid", stname);
  1507.     sprintf(stname, "name$topology%d", topid);
  1508.     topptr->topologyname = ptk_stringtoint("name", stname);
  1509.     topptr->root = root;
  1510.     topptr->topologytype = PTKEBOXTOPOLOGY;
  1511.     topptr->txfont = txfont;
  1512.     topptr->textcolour = textcol;
  1513.     topptr->linecolour = linecol;
  1514.     topptr->edgecolour = edgecol;
  1515.     topptr->intcolour = intcol;
  1516.     topptr->highlightnode = -1;
  1517.     topptr->highlightedge = intcol;
  1518.     topptr->highlightint = edgecol;
  1519.     *error = 0;
  1520.   
  1521.     if (!ptk_structexists(topptr->root)) 
  1522.     {
  1523.       *error = 1;
  1524.       fprintf(stderr, "ptk_createtopology: structure [%d] doesn't exist\n", topptr->root);
  1525.       return;
  1526.     }
  1527.   
  1528.     ptk_openstruct(topptr->topologystid);
  1529.     
  1530.     initialise();
  1531.     getpaths();
  1532.     buildlists();
  1533.   
  1534.     ptk_seteditmode(PEDIT_INSERT);   /* We want to insert elements */
  1535.     nameset.ints = &name;
  1536.     nameset.num_ints = 1;
  1537.     name = topptr->topologyname;
  1538.     padd_names_set(&nameset);
  1539.     plabel(ptk_stringtoint("label", "globaltran"));
  1540.     plabel(ptk_stringtoint("label", "highlightattrs"));
  1541.     pset_edge_colr_ind(topptr->highlightedge);
  1542.     pset_int_colr_ind(topptr->highlightint);  
  1543.     pset_int_style(PSTYLE_SOLID);
  1544.     pset_edge_flag(PEDGE_ON);
  1545.     plabel(ptk_stringtoint("label", "highlightnode"));
  1546.     plabel(ptk_stringtoint("label", "attrs"));
  1547.     pset_line_colr_ind(topptr->linecolour);
  1548.     pset_int_colr_ind(topptr->intcolour);
  1549.     pset_edge_colr_ind(topptr->edgecolour);
  1550.     pset_text_font(topptr->txfont);
  1551.     pset_text_colr_ind(topptr->textcolour);
  1552.     plabel(ptk_stringtoint("label", "starttopology"));
  1553.   
  1554.     placenodes();
  1555.     drawnodes();  
  1556.     premove_names_set(&nameset);
  1557.     drawconnections();
  1558.     drawnames();
  1559.   
  1560.     /* In case any nodes were labelled with keys because there was no room
  1561.        for proper annotation, draw the keytable. */
  1562.     drawkeys();
  1563.     plabel(ptk_stringtoint("label", "endtopology"));
  1564.  
  1565.     /* now we've drawn it all, so we find the appropriate scale to put it all
  1566.        in [0,1] */
  1567.     setscaling();
  1568.   
  1569.     ptk_unseteditmode();
  1570.     ptk_closestruct();
  1571.   }
  1572.   else
  1573.   {
  1574.     *error = 2;
  1575.   }
  1576. }  /* createtopology */
  1577.  
  1578. /*--------------------------------------------------------------------------*/
  1579.  
  1580. /*function:external*/
  1581. extern void ptk_createtopology(C(Pint) topid, C(Pint) root, C(Pint *) err)
  1582. PreANSI(Pint topid)
  1583. PreANSI(Pint root)
  1584. PreANSI(Pint *err)
  1585. /* 
  1586. ** \parambegin
  1587. ** \param{Pint}{topid}{topology identifier}{IN}
  1588. ** \param{Pint}{root}{structure network identifier}{IN}
  1589. ** \param{Pint *}{error}{error code}{OUT}
  1590. ** \paramend
  1591. ** \blurb{This function creates a diagram of the structure network
  1592. ** specified by {\tt root}. The diagram is a PHIGS structure which
  1593. ** uses boxes connected by lines to represent structures and
  1594. ** EXECUTE STRUCTURE elements. The error code = 1 if the root structure
  1595. ** does not exist and = 2 if {\tt topid} already exists.
  1596. ** This function requires hashtables "structureid", "label", "name".} 
  1597. */
  1598. {
  1599.   createtopology(topid, root, 1, 1, 1, 1, 0, err);
  1600. }  /* ptk_createtopology */
  1601.  
  1602. /*--------------------------------------------------------------------------*/
  1603.  
  1604. /*function:external*/
  1605. extern void ptk_settopologyattrs(C(Pint) topid, C(Pint) txfont,
  1606.                          C(Pint) linecol, C(Pint) textcol, C(Pint) edgecol,
  1607.                          C(Pint) intcol, C(Pint) htedgecol, C(Pint) htintcol)
  1608. PreANSI(Pint topid)
  1609. PreANSI(Pint txfont)
  1610. PreANSI(Pint linecol)
  1611. PreANSI(Pint textcol)
  1612. PreANSI(Pint edgecol)
  1613. PreANSI(Pint intcol)
  1614. PreANSI(Pint htedgecol)
  1615. PreANSI(Pint htintcol)
  1616. /* 
  1617. ** \parambegin
  1618. ** \param{Pint}{topid}{topology identifier}{IN}
  1619. ** \param{Pint}{txfont}{label text font}{IN}
  1620. ** \param{Pint}{linecol}{polyline colour index}{IN}
  1621. ** \param{Pint}{textcol}{text colour index}{IN}
  1622. ** \param{Pint}{edgecol}{edge colour index}{IN}
  1623. ** \param{Pint}{intcol}{interior colour index}{IN}
  1624. ** \param{Pint}{htedgecol}{highlight edge colour index}{IN}
  1625. ** \param{Pint}{htintcol}{highlight interior colour index}{IN}
  1626. ** \paramend
  1627. ** \blurb{This function sets the text font and colour attribute values 
  1628. ** of a topology diagram. The text font applies to the structure
  1629. ** names which are extracted from the \"structureid\" hashtable.
  1630. ** The highlight colour indicies are used to highlight a single
  1631. ** topology node in the function {\tt ptk\_settopologyhighlightnode}.}
  1632. */
  1633. {
  1634.   settop(topid);
  1635.   if (topptr != NULL)
  1636.   {  
  1637.     topptr->txfont = txfont;
  1638.     topptr->textcolour = textcol;
  1639.     topptr->linecolour = linecol;
  1640.     topptr->edgecolour = edgecol;
  1641.     topptr->intcolour = intcol;
  1642.     topptr->highlightedge = htedgecol;
  1643.     topptr->highlightint = htintcol;
  1644.     redrawtopology();
  1645.   }
  1646. }  /* ptk_settopologyattrs */
  1647.  
  1648. /*--------------------------------------------------------------------------*/
  1649.  
  1650. /*function:external*/
  1651. extern void ptk_inqtopologyattrs(C(Pint) topid, C(Pint *) txfont,
  1652.                   C(Pint *) linecol, C(Pint *) textcol, C(Pint *) edgecol,
  1653.                   C(Pint *) intcol, C(Pint *) htedgecol, C(Pint *) htintcol,
  1654.                   C(Pint *) err)
  1655. PreANSI(Pint topid)
  1656. PreANSI(Pint *txfont)
  1657. PreANSI(Pint *linecol)
  1658. PreANSI(Pint *textcol)
  1659. PreANSI(Pint *edgecol)
  1660. PreANSI(Pint *intcol)
  1661. PreANSI(Pint *htedgecol)
  1662. PreANSI(Pint *htintcol)
  1663. PreANSI(Pint *err)
  1664. /* 
  1665. ** \parambegin
  1666. ** \param{Pint}{topid}{topology identifier}{IN}
  1667. ** \param{Pint *}{txfont}{label text font}{OUT}
  1668. ** \param{Pint *}{linecol}{polyline colour index}{OUT}
  1669. ** \param{Pint *}{textcol}{text colour index}{OUT}
  1670. ** \param{Pint *}{edgecol}{edge colour index}{OUT}
  1671. ** \param{Pint *}{intcol}{interior colour index}{OUT}
  1672. ** \param{Pint *}{htedgecol}{highlight edge colour index}{OUT}
  1673. ** \param{Pint *}{htintcol}{highlight interior colour index}{OUT}
  1674. ** \param{Pint *}{err}{error indicator}{OUT}
  1675. ** \paramend
  1676. ** \blurb{This function may be used to obtain the text font and
  1677. ** colour attribute values of a topology diagram. The error code = 1
  1678. ** if {\tt topid} doesn't exist.}
  1679. */
  1680. {
  1681.   *err = 0;
  1682.   settop(topid);
  1683.   if (topptr != NULL)
  1684.   {  
  1685.     *txfont = topptr->txfont;
  1686.     *textcol = topptr->textcolour;
  1687.     *linecol = topptr->linecolour;
  1688.     *edgecol = topptr->edgecolour;
  1689.     *intcol = topptr->intcolour;
  1690.     *htedgecol = topptr->highlightedge;
  1691.     *htintcol = topptr->highlightint;
  1692.     redrawtopology();
  1693.   }
  1694.   else
  1695.     *err = 1;
  1696. }  /* ptk_inqtopologyattrs */
  1697.  
  1698. /*--------------------------------------------------------------------------*/
  1699.  
  1700. /*function:external*/
  1701. extern void ptk_createtopologypaths(C(Pint) topid, 
  1702.                      C(Pelem_ref_list_list *) paths, C(Pint *) error)
  1703. PreANSI(Pint topid)
  1704. PreANSI(Pelem_ref_list_list *paths)
  1705. PreANSI(Pint *error)
  1706. /* 
  1707. ** \parambegin
  1708. ** \param{Pint}{topid}{topology identifier}{IN}
  1709. ** \param{Pelem\_ref\_list\_list *}{paths}{structure-element paths}{IN}
  1710. ** \param{Pint *}{error}{error code}{OUT}
  1711. ** \paramend
  1712. ** \blurb{This function creates a topology diagram using the structure
  1713. ** path list {\tt paths}. This enables a topology diagram to be built
  1714. ** of a non-existent structure network or of a subset of an actual
  1715. ** structure network. The error code = 1 if {\tt topid} already exists.
  1716. ** This function requires hashtables "structureid", "label", "name".} 
  1717. */
  1718. {
  1719.   Pint curname;
  1720.   char stname[255];
  1721.   Pint_list nameset;
  1722.   Pint name;
  1723.  
  1724.   *error = 0;
  1725.   settop(topid);
  1726.   if (topptr == NULL)
  1727.   {
  1728.     if (lasttop == NULL)
  1729.     {
  1730.       firsttop = lasttop = topptr =
  1731.         (ptkstopdraw *)malloc(sizeof(ptkstopdraw));
  1732.       topptr->next = NULL;
  1733.     }
  1734.     else
  1735.     {
  1736.       lasttop->next = topptr = (ptkstopdraw *)malloc(sizeof(ptkstopdraw));
  1737.       topptr->next = NULL;
  1738.       lasttop = lasttop->next;
  1739.     }
  1740.  
  1741.     topologycount++;  
  1742.     topptr->topologyid = topid;
  1743.     topptr->posted.num_ints = 0;
  1744.     topptr->posted.ints = (Pint *)calloc(10, sizeof(Pint));
  1745.     sprintf(stname, "ptk$topology%d", topid);
  1746.     topptr->topologystid = ptk_stringtoint("structureid", stname);
  1747.     sprintf(stname, "name$topology%d", topid);
  1748.     topptr->topologyname = ptk_stringtoint("name", stname);
  1749.     topptr->topologytype = PTKEBOXTOPOLOGY;
  1750.     topptr->txfont = 1;
  1751.     topptr->textcolour = 1;
  1752.     topptr->linecolour = 1;
  1753.     topptr->edgecolour = 1;
  1754.     topptr->intcolour = 0;
  1755.     topptr->highlightnode = -1;
  1756.     topptr->highlightedge = 0;
  1757.     topptr->highlightint = 1;
  1758.   
  1759.     if (paths->num_elem_ref_lists > 0)
  1760.     {
  1761.       topptr->root = paths->elem_ref_lists[0].elem_refs[0].struct_id;
  1762.   
  1763.       ptk_openstruct(topptr->topologystid);  
  1764.       initialise();
  1765.       topptr->pathlist = paths;
  1766.       buildlists();
  1767.     
  1768.       ptk_seteditmode(PEDIT_INSERT);   /* We want to insert elements */
  1769.       nameset.ints = &name;
  1770.       nameset.num_ints = 1;
  1771.       name = topptr->topologyname;
  1772.       padd_names_set(&nameset);  
  1773.       plabel(ptk_stringtoint("label", "globaltran"));
  1774.  
  1775.       plabel(ptk_stringtoint("label", "highlightattrs"));
  1776.       pset_edge_colr_ind(topptr->highlightedge);
  1777.       pset_int_colr_ind(topptr->highlightint);    
  1778.       pset_int_style(PSTYLE_SOLID);
  1779.       pset_edge_flag(PEDGE_ON);
  1780.       plabel(ptk_stringtoint("label", "highlightnode"));
  1781.       plabel(ptk_stringtoint("label", "attrs"));
  1782.       pset_line_colr_ind(topptr->linecolour);
  1783.       pset_int_colr_ind(topptr->intcolour);
  1784.       pset_edge_colr_ind(topptr->edgecolour);
  1785.       pset_text_font(topptr->txfont);
  1786.       pset_text_colr_ind(topptr->textcolour);
  1787.       plabel(ptk_stringtoint("label", "starttopology"));
  1788.     
  1789.       placenodes();
  1790.       drawnodes();
  1791.       premove_names_set(&nameset);
  1792.       drawconnections();
  1793.       drawnames();
  1794.     
  1795.       /* In case any nodes were labelled with keys because there was no room
  1796.          for proper annotation, draw the keytable. */
  1797.       drawkeys();
  1798.       plabel(ptk_stringtoint("label", "endtopology"));
  1799.  
  1800.       /* now we've drawn it all, so we find the appropriate scale to put it all
  1801.          in [0,1] */
  1802.       setscaling();
  1803.     
  1804.       ptk_unseteditmode();
  1805.       ptk_closestruct();
  1806.     }
  1807.   }
  1808.   else
  1809.     *error = 1;
  1810. }  /* ptk_createtopologypaths */
  1811.  
  1812. /*--------------------------------------------------------------------------*/
  1813.  
  1814. /*function:external*/
  1815. extern void ptk_settopologytype(C(Pint) topid, C(ptketopologytype) toptype)
  1816. PreANSI(Pint topid)
  1817. PreANSI(ptketopologytype toptype)
  1818. /*
  1819. ** \parambegin
  1820. ** \param{Pint}{topid}{topology identifier}{IN}
  1821. ** \param{ptketopologytype}{toptype}{topology type}{IN}
  1822. ** \paramend
  1823. ** \blurb{This function sets the type of a topology diagram to 
  1824. ** BOX, STRUCT or STRUCTNET. The BOX topology type is the default and
  1825. ** the STRUCT and STRUCTNET types insert parts of the actual structures
  1826. ** into the nodes. As a result these topology types do not work well
  1827. ** for networks containing SET VIEW INDEX and SET GLOBAL TRANSFORMATION
  1828. ** elements.}
  1829. */
  1830. {
  1831.   settop(topid);
  1832.   if (topptr != NULL)
  1833.   {
  1834.     if (topptr->topologytype != toptype)
  1835.     {
  1836.       if (topptr->topologytype == PTKESTRUCTTOPOLOGY)
  1837.         delstructnodes();
  1838.       topptr->topologytype = toptype;
  1839.       redrawtopology();
  1840.     }
  1841.   }
  1842. }  /* ptk_settopologytype */
  1843.  
  1844. /*--------------------------------------------------------------------------*/
  1845.  
  1846. /*function:external*/
  1847. extern void ptk_inqtopologytype(C(Pint) topid, C(ptketopologytype *) toptype,
  1848.                                 C(Pint *) err)
  1849. PreANSI(Pint topid)
  1850. PreANSI(ptketopologytype *toptype)
  1851. PreANSI(Pint *err)
  1852. /*
  1853. ** \parambegin
  1854. ** \param{Pint}{topid}{topology identifier}{IN}
  1855. ** \param{ptketopologytype *}{toptype}{topology type}{OUT}
  1856. ** \param{Pint *}{err}{error indicator}{OUT}
  1857. ** \paramend
  1858. ** \blurb{This function may be used to obtain the type of a topology
  1859. ** diagram. The possible types are BOX, STRUCT and STRUCTNET, with BOX
  1860. ** as the default. The error code = 1 if {\tt topid} doesn't exist.}
  1861. */
  1862. {
  1863.   *err = 0;
  1864.   settop(topid);
  1865.   if (topptr != NULL)
  1866.   {
  1867.     *toptype = topptr->topologytype;
  1868.   }
  1869.   else
  1870.     *err = 1;
  1871. }  /* ptk_inqtopologytype */
  1872.  
  1873. /*--------------------------------------------------------------------------*/
  1874.  
  1875. /*function:external*/
  1876. extern void ptk_setnodeposition(C(Pint) topid, C(Pint) structid, 
  1877.                                C(Ppoint *) nodept, C(ptkenodetype) nodetype)
  1878. PreANSI(Pint topid)
  1879. PreANSI(Pint structid)
  1880. PreANSI(Ppoint *nodept)
  1881. PreANSI(ptkenodetype nodetype)
  1882. /*
  1883. ** \parambegin
  1884. ** \param{Pint}{topid}{topology identifier}{IN}
  1885. ** \param{Pint}{structid}{structure identifier}{IN}
  1886. ** \param{Ppoint *}{nodept}{node position}{IN}
  1887. ** \param{ptkenodetype}{nodetype}{type of node}{IN}
  1888. ** \paramend
  1889. ** \blurb{This function sets the position of a topology node or group
  1890. ** of nodes. The position is given in the range [0, 1].
  1891. ** The node is specified using the structure identifier of the structure
  1892. ** that it represents. If nodetype is set to GROUP then all descendent
  1893. ** nodes of {\tt structid} are moved relative to it.}
  1894. */
  1895. {
  1896.   ptksstruct *structptr;
  1897.   Pint nodeid;
  1898.   ptkboolean found;
  1899.  
  1900.   nodeid = 0;
  1901.   settop(topid);
  1902.   if (topptr != NULL)
  1903.   {
  1904.     structptr = topptr->structlist;
  1905.     found = FALSE;
  1906.     while ((!found) && (structptr != NULL))
  1907.     {
  1908.       if (structptr->name == structid)
  1909.         found = TRUE;
  1910.       else
  1911.         nodeid++;
  1912.       structptr = structptr->next;
  1913.     }
  1914.     if (found)
  1915.       setnodeposition(topid, nodeid, nodept, nodetype);
  1916.   }
  1917. }  /* ptk_setnodeposition */
  1918.  
  1919. /*--------------------------------------------------------------------------*/
  1920.  
  1921. /*function:external*/
  1922. extern void ptk_inqnodeposition(C(Pint) topid, C(Pint) structid, 
  1923.                                C(Ppoint *) nodept, C(Pint *) err)
  1924. PreANSI(Pint topid)
  1925. PreANSI(Pint structid)
  1926. PreANSI(Ppoint *nodept)
  1927. PreANSI(Pint *err)
  1928. /*
  1929. ** \parambegin
  1930. ** \param{Pint}{topid}{topology identifier}{IN}
  1931. ** \param{Pint}{structid}{structure identifier}{IN}
  1932. ** \param{Ppoint *}{nodept}{node position}{OUT}
  1933. ** \param{Pint *}{err}{error indicator}{OUT}
  1934. ** \paramend
  1935. ** \blurb{This function may be used to obtain the position of a topology 
  1936. ** node in a topology diagram. The position is returned in the range [0, 1]. 
  1937. ** The node is specified using the structure
  1938. ** identifier of the structure that it represents. The error code = 1
  1939. ** if {\tt topid} doesn't exist and = 2 if {\tt structid} is not a node
  1940. ** in the topology.}
  1941. */
  1942. {
  1943.   ptksstruct *structptr;
  1944.   Pint nodeid;
  1945.   Ppoint3 nodept3;
  1946.   ptkboolean found;
  1947.  
  1948.   *err = 0;
  1949.   nodeid = 0;
  1950.   settop(topid);
  1951.   if (topptr != NULL)
  1952.   {
  1953.     structptr = topptr->structlist;
  1954.     found = FALSE;
  1955.     while ((!found) && (structptr != NULL))
  1956.     {
  1957.       if (structptr->name == structid)
  1958.         found = TRUE;
  1959.       else
  1960.         nodeid++;
  1961.       structptr = structptr->next;
  1962.     }
  1963.     if (found)
  1964.     {
  1965.       nodept3 = ptk_point3(structptr->pos.x, structptr->pos.y, 0.0);
  1966.       nodept3 = ptk_transform3(topptr->globaltran, &nodept3);
  1967.       *nodept = ptk_point(nodept3.x, nodept3.y);
  1968.     }
  1969.     else
  1970.       *err = 2;
  1971.   }
  1972.   else
  1973.     *err = 1;
  1974. }  /* ptk_inqnodeposition */
  1975.  
  1976. /*--------------------------------------------------------------------------*/
  1977.  
  1978. /*function:external*/
  1979. extern void ptk_tidytopology(C(Pint) wsid, C(Pint) topid, 
  1980.             C(ptkenodetype) nodetype,
  1981.             C(Pint) pickdev, C(Pint) pickpet, C(Ppick_data *) pickdatarec,
  1982.             C(Pint) locdev, C(Pint) locpet, C(Ploc_data *) locdatarec)
  1983. PreANSI(Pint wsid)
  1984. PreANSI(Pint topid)
  1985. PreANSI(ptkenodetype nodetype)
  1986. PreANSI(Pint pickdev)
  1987. PreANSI(Pint pickpet)
  1988. PreANSI(Ppick_data *pickdatarec)
  1989. PreANSI(Pint locdev)
  1990. PreANSI(Pint locpet)
  1991. PreANSI(Ploc_data *locdatarec)
  1992. /*
  1993. ** \parambegin
  1994. ** \param{Pint}{wsid}{workstation identifier}{IN}
  1995. ** \param{Pint}{topid}{topology identifier}{IN}
  1996. ** \param{ptkenodetype}{nodetype}{type of node}{IN}
  1997. ** \param{Pint}{pickdev}{pick device}{IN}
  1998. ** \param{Pint}{pickpet}{pick prompt/echo type}{IN}
  1999. ** \param{Ppick\_data *}{pickdatarec}{pick data record}{IN}
  2000. ** \param{Pint}{locdev}{locator device}{IN}
  2001. ** \param{Pint}{locpet}{locator prompt/echo type}{IN}
  2002. ** \param{Ploc\_data *}{locdatarec}{locator data record}{IN}
  2003. ** \paramend
  2004. ** \blurb{This function enables the user to set the position of
  2005. ** a topology node, or group of nodes, interactively. The pick device
  2006. ** {\tt pickdev} is used to request a topology node and if
  2007. ** successful the locator device {\tt locdev} is used to specify
  2008. ** a new node position. Prompt and echo types may be set for both
  2009. ** the pick and locator devices.}
  2010. */
  2011. {
  2012.   Pint nodeid, inclnames, i, initview, viewindex;
  2013.   ptkboolean found;
  2014.   Ppick_path initpath, pick;
  2015.   Plimit3 echo;
  2016.   Ppick_path_elem pathel[10];
  2017.   Pfloat maxdevx, maxdevy, maxdevz;
  2018.   Pfilter pickfilt;
  2019.   Pin_status status;
  2020.   Ppoint initpos, locpos;
  2021.  
  2022.   settop(topid);
  2023.   if (topptr != NULL)
  2024.   {
  2025.     ptk_inqmaxdevicecoords3(wsid, &maxdevx, &maxdevy, &maxdevz);
  2026.     echo = ptk_limit3(0.0, maxdevx, 0.0, maxdevy, 0.0, maxdevz);
  2027.     /* pick topology node */
  2028.     pset_pick_mode(wsid, pickdev, POP_REQ, PSWITCH_ECHO);
  2029.     initpath.depth = 0;
  2030.     /* Implementation dependent code because of differences in
  2031.     ** valid initial status.
  2032.     */
  2033. #ifdef SUN
  2034.     pinit_pick3(wsid, pickdev, PIN_STATUS_NONE, &initpath, pickpet, &echo, 
  2035.                 pickdatarec, PORDER_TOP_FIRST);
  2036. #endif
  2037. #ifdef HP
  2038.     pinit_pick3(wsid, pickdev, PIN_STATUS_NO_IN, &initpath, pickpet, &echo, 
  2039.                 pickdatarec, PORDER_TOP_FIRST);
  2040. #endif
  2041.     pset_pick_mode(wsid, pickdev, POP_REQ, PSWITCH_ECHO);
  2042.     pickfilt.incl_set.num_ints = 1;
  2043.     pickfilt.incl_set.ints = &inclnames;
  2044.     inclnames = topptr->topologyname;
  2045.     pickfilt.excl_set.num_ints = 0;
  2046.     pset_pick_filter(wsid, pickdev, &pickfilt);
  2047.     pick.path_list = pathel;
  2048.     preq_pick(wsid, pickdev, 10, &status, &pick);
  2049.     if (status != PIN_STATUS_OK)
  2050.       return;
  2051.   
  2052.     /* find picked node */
  2053.     i = 0;
  2054.     found = FALSE;
  2055.     while ((!found) && (i < 10))
  2056.     {
  2057.       if (pick.path_list[i].struct_id == topptr->topologystid)
  2058.       {
  2059.         nodeid = pick.path_list[i].pick_id;
  2060.         found = TRUE;
  2061.       }
  2062.       i++;
  2063.     }
  2064.     /* locate point */
  2065.     pset_loc_mode(wsid, locdev, POP_REQ, PSWITCH_ECHO);
  2066.     initview = 0;
  2067.     initpos = ptk_point(0.5, 0.5);
  2068.     pinit_loc(wsid, locdev, initview, &initpos, locpet, &echo, locdatarec);
  2069.     pset_loc_mode(wsid, locdev, POP_REQ, PSWITCH_ECHO);
  2070.     preq_loc(wsid, locdev, &status, &viewindex, &locpos);
  2071.     
  2072.     if (status == PIN_STATUS_NONE)
  2073.       return;
  2074.   
  2075.     ptk_setnodeposition(topid, nodeid, &locpos, nodetype);
  2076.   }
  2077. }  /* ptk_tidytopology */
  2078.  
  2079. /*--------------------------------------------------------------------------*/
  2080.  
  2081. /*function:external*/
  2082. extern void ptk_posttopology(C(Pint) wsid, C(Pint) topid, C(Pfloat) priority)
  2083. PreANSI(Pint wsid)
  2084. PreANSI(Pint topid)
  2085. PreANSI(Pfloat priority)
  2086. /*
  2087. ** \parambegin
  2088. ** \param{Pint}{wsid}{workstation identifier}{IN}
  2089. ** \param{Pint}{topid}{topology identifier}{IN}
  2090. ** \param{Pfloat}{priority}{display priority}{IN}
  2091. ** \paramend
  2092. ** \blurb{This function posts a topology diagram structure to the
  2093. ** workstation {\tt wsid}.}
  2094. */
  2095. {
  2096.   settop(topid);
  2097.   if (topptr != NULL)
  2098.   {
  2099.     ptk_poststruct(wsid, topptr->topologystid, priority);
  2100.     addtointlst(wsid, &topptr->posted);
  2101.   }
  2102. }  /* ptk_posttopology */
  2103.  
  2104. /*--------------------------------------------------------------------------*/
  2105.  
  2106. /*function:external*/
  2107. extern void ptk_unposttopology(C(Pint) wsid, C(Pint) topid)
  2108. PreANSI(Pint wsid)
  2109. PreANSI(Pint topid)
  2110. /*
  2111. ** \parambegin
  2112. ** \param{Pint}{wsid}{workstation identifier}{IN}
  2113. ** \param{Pint}{topid}{topology identifier}{IN}
  2114. ** \paramend
  2115. ** \blurb{This function unposts the topology diagram structure from
  2116. ** the workstation {\tt wsid}.}
  2117. */
  2118. {
  2119.   settop(topid);
  2120.   if (topptr != NULL)
  2121.   {
  2122.     punpost_struct(wsid, topptr->topologystid);
  2123.     removefromintlst(wsid, &topptr->posted);
  2124.   }
  2125. }  /* ptk_unposttopology */
  2126.  
  2127. /*--------------------------------------------------------------------------*/
  2128.  
  2129. /*function:external*/
  2130. extern ptkboolean ptk_deltopology(C(Pint) topid)
  2131. PreANSI(Pint topid)
  2132. /*
  2133. ** \parambegin
  2134. ** \param{Pint}{topid}{topology identifier}{IN}
  2135. ** \paramend
  2136. ** \blurb{This function deletes a topology diagram from the PHIGS Toolkit
  2137. ** topology store. The function returns TRUE if a topology is deleted, 
  2138. ** otherwise FALSE.}
  2139. */
  2140. {
  2141.   ptkstopdraw *ptr, *junk;
  2142.   char stname[20];
  2143.  
  2144.   settop(topid);
  2145.   if (topptr != NULL)
  2146.   {
  2147.     if (topptr->topologytype == PTKESTRUCTTOPOLOGY)
  2148.       delstructnodes();
  2149.     ptr = firsttop;
  2150.     if (ptr->topologyid == topid)
  2151.     {
  2152.       firsttop = firsttop->next;
  2153.       if (lasttop->topologyid == topid)
  2154.         lasttop = firsttop;
  2155.     }
  2156.     else
  2157.     {
  2158.       while (ptr->next->topologyid != topid)
  2159.       {
  2160.         ptr = ptr->next;
  2161.         if (ptr->next == NULL)
  2162.           return FALSE;
  2163.       }
  2164.       junk = ptr->next;
  2165.       ptr->next = junk->next;
  2166.       if (ptr->next == NULL)
  2167.         lasttop = ptr;
  2168.     }
  2169.     pdel_struct(ptr->topologystid);
  2170.     /* dispose structlist */
  2171.     if (ptr->structlist != NULL)
  2172.       disposestructlist(ptr->structlist);
  2173.     /* dispose rowlist */
  2174.     if (ptr->rowlist != NULL)
  2175.       disposerowlist(ptr->rowlist);
  2176.     free(ptr);
  2177.  
  2178.     /* delete strings */
  2179.     sprintf(stname, "ptk$topology%d", topid);
  2180.     ptk_delstring("structureid", stname);
  2181.     sprintf(stname, "name$topology%d", topid);
  2182.     ptk_delstring("name", stname);
  2183.     topologycount--;
  2184.     return TRUE;
  2185.   }
  2186.   else
  2187.     return FALSE;
  2188. }  /* ptk_deltopology */
  2189.  
  2190. /*--------------------------------------------------------------------------*/
  2191.  
  2192. /*function:external*/
  2193. extern void ptk_storetopologylayout(C(FILE *) fileptr, C(Pint) topid)
  2194. PreANSI(FILE *fileptr)
  2195. PreANSI(Pint topid)
  2196. /*
  2197. ** \parambegin
  2198. ** \param{FILE *}{fileptr}{pointer to file}{OUT}
  2199. ** \param{Pint}{topid}{topology identifier}{IN}
  2200. ** \paramend
  2201. ** \blurb{This function saves a topology layout in a text file. The
  2202. ** layout refers to the positions of all the topology nodes. The
  2203. ** format of the stored layout is:
  2204. ** 
  2205. ** {\tt start}
  2206. ** {\tt (for each node in topology diagram)}
  2207. ** {\tt x y}
  2208. ** {\tt end}
  2209. ** }
  2210. */
  2211. {
  2212.   ptksstruct *structptr;
  2213.  
  2214.   settop(topid);
  2215.   if (topptr != NULL)
  2216.   {
  2217.     structptr = topptr->structlist;
  2218.     fprintf(fileptr, "\nstart\n");
  2219.     while (structptr != NULL)
  2220.     {
  2221.       fprintf(fileptr, "%f %f\n", structptr->pos.x, structptr->pos.y);
  2222.       structptr = structptr->next;
  2223.     }
  2224.     fprintf(fileptr, "end\n");
  2225.   }
  2226. }  /* ptk_storetopologylayout */
  2227.  
  2228. /*--------------------------------------------------------------------------*/
  2229.  
  2230. /*function:external*/
  2231. extern void ptk_restoretopologylayout(C(FILE *) fileptr, C(Pint) topid)
  2232. PreANSI(FILE *fileptr)
  2233. PreANSI(Pint topid)
  2234. /*
  2235. ** \parambegin
  2236. ** \param{FILE *}{fileptr}{pointer to file}{OUT}
  2237. ** \param{Pint}{topid}{topology identifier}{IN}
  2238. ** \paramend
  2239. ** \blurb{This function reads a topology layout from a text file.
  2240. ** The layout is used to reposition the nodes of the topology
  2241. ** diagram {\tt topid} but will only really make sense if the layout
  2242. ** was stored originally from the same topology.} 
  2243. */
  2244. {
  2245.   ptksstruct *structptr;
  2246.   char str[255];
  2247.   Pint_list nameset;
  2248.   Pint k;
  2249.  
  2250.   settop(topid);
  2251.   if (topptr != NULL)
  2252.   {
  2253.     structptr = topptr->structlist;
  2254.     /* find `start' */
  2255.     do
  2256.     {
  2257.       fgets(str, 255, fileptr);    
  2258.     } while (strncmp(str, "start", 5) != 0);
  2259.     fgets(str, 255, fileptr);    
  2260.     while ((structptr != NULL) && (strncmp(str, "end", 3) != 0)) 
  2261.     {
  2262.       sscanf(str, "%f %f\n", &structptr->pos.x, &structptr->pos.y);
  2263.       structptr = structptr->next;
  2264.       fgets(str, 255, fileptr);    
  2265.     }
  2266.  
  2267.     /* remove keys */
  2268.     topptr->keyno = 0;
  2269.     for (k = 0; k <= 254; k++)
  2270.       topptr->rowmaxx[k] = -32768.0;
  2271.  
  2272.     ptk_openstruct(topptr->topologystid);
  2273.     pset_elem_ptr(0);
  2274.     pdel_elems_labels(ptk_stringtoint("label", "globaltran"), 
  2275.                    ptk_stringtoint("label", "highlightattrs"));
  2276.     pdel_elems_labels(ptk_stringtoint("label", "highlightnode"), 
  2277.                    ptk_stringtoint("label", "attrs"));
  2278.     pdel_elems_labels(ptk_stringtoint("label", "starttopology"), 
  2279.                    ptk_stringtoint("label", "endtopology"));
  2280.     topptr->extent = ptk_limit3(1000000.0, -10000000.0, 10000000.0,
  2281.                                  -10000000.0, 0.0, 1.0);
  2282.     pset_edit_mode(PEDIT_INSERT);  
  2283.     setnode(1.0, 1.0);
  2284.     switch (topptr->topologytype)
  2285.     {
  2286.       case PTKEBOXTOPOLOGY: 
  2287.         drawnodes();
  2288.         break;
  2289.   
  2290.       case PTKESTRUCTNETTOPOLOGY:
  2291.         drawstructnetnodes();
  2292.         break;
  2293.   
  2294.       case PTKESTRUCTTOPOLOGY:
  2295.         drawstructnodes();
  2296.         break;
  2297.     }
  2298.     nameset.num_ints = 1;
  2299.     nameset.ints = &topptr->topologyname;
  2300.     premove_names_set(&nameset);  
  2301.     drawconnections();
  2302.     drawnames();
  2303.     drawkeys();
  2304.     setscaling();
  2305.     ptk_closestruct();
  2306.   }
  2307. }  /* ptk_restoretopologylayout */
  2308.  
  2309. /*--------------------------------------------------------------------------*/
  2310.  
  2311. /*function:external*/
  2312. extern void ptk_inqpostedtopologies(C(Pint) wsid, C(Pint) size, 
  2313.             C(Pint_list *) topids, C(Pint *) totalsize, C(Pint *) err)
  2314. PreANSI(Pint wsid)
  2315. PreANSI(Pint size)
  2316. PreANSI(Pint_list *topids)
  2317. PreANSI(Pint *totalsize)
  2318. PreANSI(Pint *err)
  2319. /*
  2320. ** \parambegin
  2321. ** \param{Pint}{wsid}{workstation identifier}{IN}
  2322. ** \param{Pint}{size}{size of buffer}{IN}
  2323. ** \param{Pint\_list *}{topids}{list of posted topologies}{OUT}
  2324. ** \param{Pint *}{totalsize}{length of posted topologies list}{OUT}
  2325. ** \param{Pint *}{err}{error indicator}{OUT}
  2326. ** \paramend
  2327. ** \blurb{This function may be used to obtain a list of all the
  2328. ** topology diagrams which are posted to the workstation {\tt wsid}.}
  2329. */
  2330. {
  2331.   ptkstopdraw *ptrtop;
  2332.  
  2333.   *err = 0;
  2334.   *totalsize = 0;
  2335.   ptrtop = firsttop;
  2336.   while (ptrtop != NULL)
  2337.   {
  2338.     if ((inintlst(wsid, &ptrtop->posted) != -1))
  2339.       (*totalsize)++;
  2340.     ptrtop = ptrtop->next;
  2341.   }
  2342.   if (size >= *totalsize)
  2343.   {
  2344.     topids->num_ints = 0;
  2345.     ptrtop = firsttop;
  2346.     while (ptrtop != NULL)
  2347.     {
  2348.       if ((inintlst(wsid, &ptrtop->posted) != -1))
  2349.       {
  2350.         topids->ints[topids->num_ints] = ptrtop->topologyid;
  2351.         topids->num_ints++;
  2352.       }
  2353.       ptrtop = ptrtop->next;
  2354.     }
  2355.   }
  2356. }  /* ptk_inqpostedtopologies */
  2357.  
  2358. /*--------------------------------------------------------------------------*/
  2359.  
  2360. /*function:external*/
  2361. extern void ptk_inqtopologyids(C(Pint) size, C(Pint_list *) topids, 
  2362.                                C(Pint *) totalsize, C(Pint *) err)
  2363. PreANSI(Pint size)
  2364. PreANSI(Pint_list *topids)
  2365. PreANSI(Pint *totalsize)
  2366. PreANSI(Pint *err)
  2367. /*
  2368. ** \parambegin
  2369. ** \param{Pint}{size}{size of buffer}{IN}
  2370. ** \param{Pint\_list *}{topids}{list of topology identifiers}{OUT}
  2371. ** \param{Pint *}{totalsize}{length of topology identifiers list}{OUT}
  2372. ** \param{Pint *}{err}{error indicator}{OUT}
  2373. ** \paramend
  2374. ** \blurb{This function may be used to obtain a list of all the topology
  2375. ** diagrams in the PHIGS Toolkit topology store.}
  2376. */
  2377. {
  2378.   ptkstopdraw *ptrtop;
  2379.  
  2380.   *err = 0;
  2381.   *totalsize = topologycount;
  2382.   if (size >= *totalsize)
  2383.   {
  2384.     topids->num_ints = 0;
  2385.     ptrtop = firsttop;
  2386.     while (ptrtop != NULL)
  2387.     {
  2388.       topids->ints[topids->num_ints] = ptrtop->topologyid;
  2389.       topids->num_ints++;
  2390.       ptrtop = ptrtop->next;
  2391.     }
  2392.   }
  2393. }  /* ptk_inqtopologyids */
  2394.  
  2395. /*--------------------------------------------------------------------------*/
  2396.  
  2397. /*function:external*/
  2398. extern void ptk_inqtopologystructid(C(Pint) topid, C(Pint *) topstid,
  2399.                                     C(Pint *) err)
  2400. PreANSI(Pint topid)
  2401. PreANSI(Pint *topstid)
  2402. PreANSI(Pint *err)
  2403. /*
  2404. ** \parambegin
  2405. ** \param{Pint}{topid}{topology identifier}{IN}
  2406. ** \param{Pint *}{topstid}{topology structure identifier}{IN}
  2407. ** \param{Pint *}{err}{error indicator}{OUT}
  2408. ** \paramend
  2409. ** \blurb{This function may be used to obtain the structure identifier 
  2410. ** of the topology diagram {\tt topid}. In the case of the BOX topology
  2411. ** type the diagram is a single PHIGS structure but for STRUCT and
  2412. ** STRUCTNET type diagrams it is a structure network. 
  2413. ** The error code = 1 if {\tt topid} doesn't exist.}
  2414. */
  2415. {
  2416.   *err = 0;
  2417.   settop(topid);
  2418.   if (topptr != NULL)
  2419.     *topstid = topptr->topologystid;
  2420.   else
  2421.     *err = 1;
  2422. }  /* ptk_inqtopologystructid */
  2423.  
  2424. /*--------------------------------------------------------------------------*/
  2425.  
  2426. /*function:external*/
  2427. extern void ptk_inqtopologyname(C(Pint) topid, C(Pint *) name, C(Pint *) err) 
  2428. PreANSI(Pint topid)
  2429. PreANSI(Pint *name)
  2430. PreANSI(Pint *err)
  2431. /*
  2432. ** \parambegin
  2433. ** \param{Pint}{topid}{topology identifier}{IN}
  2434. ** \param{Pint *}{name}{topology name for nameset filters}{OUT}
  2435. ** \param{Pint *}{err}{error indicator}{OUT}
  2436. ** \paramend
  2437. ** \blurb{This function may be used to obtain the topology name for use 
  2438. ** in the pick filter. When a topology name is added to the pick filter
  2439. ** only the topology nodes are pickable.
  2440. ** The error code = 1 if {\tt topid} doesn't exist.}
  2441. */
  2442. {
  2443.   *err = 0;
  2444.   settop(topid);
  2445.   if (topptr != NULL)
  2446.   {
  2447.     *name = topptr->topologyname;
  2448.   }
  2449.   else
  2450.     *err = 1;
  2451. }  /* ptk_inqtopologyname */
  2452.  
  2453. /*--------------------------------------------------------------------------*/
  2454.  
  2455. /*function:external*/
  2456. extern void ptk_settopologyhighlightnode(C(Pint) topid, C(Pint) topnodestid)
  2457. PreANSI(Pint topid)
  2458. PreANSI(Pint topnodestid)
  2459. /*
  2460. ** \parambegin
  2461. ** \param{Pint}{topid}{topology identifier}{IN}
  2462. ** \param{Pint}{topnodestid}{topology node structure identifier}{IN}
  2463. ** \paramend
  2464. ** \blurb{This function highlights a single topology node by
  2465. ** setting the colour attribute values of the edge and interior of
  2466. ** the node box. This function only works for BOX topology types.}
  2467. */
  2468. {
  2469.   Pint nodeid;
  2470.   ptksstruct *structptr;
  2471.   ptkboolean found;
  2472.  
  2473.   found = FALSE;
  2474.   nodeid = 0;
  2475.   settop(topid);
  2476.   if (topptr != NULL)
  2477.   {
  2478.     structptr = topptr->structlist;
  2479.     while ((structptr != NULL) && (!found))
  2480.     {
  2481.       if (structptr->name == topnodestid)
  2482.         found = TRUE;
  2483.       else
  2484.         nodeid++;
  2485.       structptr = structptr->next;
  2486.     }
  2487.     if (found)
  2488.     {
  2489.       topptr->highlightnode = nodeid;
  2490.       redrawtopology();
  2491.     }
  2492.   }
  2493. }  /* ptk_settopologyhighlightnode */
  2494.  
  2495. /*--------------------------------------------------------------------------*/
  2496.  
  2497. /*function:external*/
  2498. extern void ptk_inqtopologyhighlightnode(C(Pint) topid, 
  2499.                               C(Pint *) topnodestid, C(Pint *) err)
  2500. PreANSI(Pint topid)
  2501. PreANSI(Pint *topnodestid)
  2502. PreANSI(Pint *err)
  2503. /*
  2504. ** \parambegin
  2505. ** \param{Pint}{topid}{topology identifier}{IN}
  2506. ** \param{Pint *}{topnodestid}{topology node structure identifier}{OUT}
  2507. ** \param{Pint *}{err}{error indicator}{OUT}
  2508. ** \paramend
  2509. ** \blurb{This function may be used to obtain the structure
  2510. ** identifier of the currently highlighted topology node. The error code
  2511. ** = 1 if {\tt topid} doesn't exist and = 2 if there is no
  2512. ** highlighted node.}
  2513. */
  2514. {
  2515.   Pint i;
  2516.   ptksstruct *structptr;
  2517.  
  2518.   *err = 0;
  2519.   settop(topid);
  2520.   if (topptr != NULL)
  2521.   {
  2522.     if (topptr->highlightnode != -1)
  2523.     {
  2524.       structptr = topptr->structlist;
  2525.       for (i = 0; i < topptr->highlightnode; i++)
  2526.         structptr = structptr->next;    
  2527.       *topnodestid = structptr->name;
  2528.     }
  2529.     else
  2530.       *err = 2;
  2531.   }
  2532.   else
  2533.     *err = 1;
  2534. }  /* ptk_inqtopologyhighlightnode */
  2535.  
  2536. /*--------------------------------------------------------------------------*/
  2537.  
  2538. /* end of topo.c */
  2539.  
  2540.